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

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

1С: как найти значение в табличной части

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

Поиск значения в табличной части — одна из самых частых задач при доработке конфигураций 1С: нужно проверить, есть ли товар в документе, найти строку по номенклатуре, определить, не задублировалась ли запись. Платформа 1С:Предприятие предлагает несколько способов решения: метод Найти(), метод НайтиСтроки() и обычный перебор строк в цикле. У каждого подхода есть свои условия применения, ограничения и подводные камни.

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

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

Что такое табличная часть и как к ней обратиться

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

Если код выполняется в модуле формы, обращение зависит от типа формы. В управляемой форме данные объекта доступны через реквизит формы: Объект.Товары. В модуле объекта (например, при проведении документа) табличная часть доступна напрямую: Товары или ЭтотОбъект.Товары.

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

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

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

Метод возвращает строку табличной части, если совпадение найдено, или Неопределено, если подходящих строк нет. Проверка результата обязательна: обращение к колонке через Неопределено вызовет ошибку выполнения. Типовой шаблон выглядит так:

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

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

// Товара в табличной части нет — добавляем строку

СтрокаТовара = Объект.Товары.Добавить();

СтрокаТовара.Номенклатура = Номенклатура;

Иначе

// Товар найден — увеличиваем количество

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

КонецЕсли;

Учитывайте, что сравнение значений идёт строго по типу и значению. Если искать строку «100» в колонке с числовым типом, совпадения не будет. Аналогично ссылка на элемент справочника не равна строке с его наименованием — частая причина «не находит, хотя значение есть».

Порядок действий при поиске через Найти()
  1. 1
    Определите имя табличной части и колонки в конфигураторе
  2. 2
    Убедитесь, что тип искомого значения совпадает с типом колонки
  3. 3
    Вызовите Найти(Значение, "ИмяКолонки") и сохраните результат в переменную
  4. 4
    Проверьте результат на Неопределено перед обращением к колонкам строки
  5. 5
    Выполните нужное действие: изменение строки, добавление новой или сообщение пользователю

Метод НайтиСтроки(): поиск всех совпадений и отбор по нескольким колонкам

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

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

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

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

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

Если НайденныеСтроки.Количество() > 0 Тогда

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

СтрокаТовара.Цена = НоваяЦена;

КонецЦикла;

КонецЕсли;

Условия в структуре отбора объединяются по логике «И»: строка попадёт в результат, только если совпадают все указанные колонки. Отбор по логике «ИЛИ» этим методом не реализуется — для таких случаев нужен перебор в цикле или последовательные вызовы с объединением результатов.

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

Сравнение способов поиска

Найти()

Одна колонка, нужна первая найденная строка. Возвращает строку или Неопределено. Не подходит, если совпадений несколько и важны все.

НайтиСтроки()

Несколько колонок по логике «И» или все совпадения. Возвращает массив строк. Не поддерживает «ИЛИ» и сложные условия.

Перебор в цикле

Сложные условия: «ИЛИ», сравнение «больше/меньше», проверка вычисляемых выражений. Универсален, но требует больше кода.

Запрос к табличной части

Нужен отбор с группировкой, итогами или соединением с другими данными. Работает только на сервере, требует выгрузки ТЧ в запрос.

Перебор строк в цикле: сложные условия поиска

Цикл применяется, когда условие поиска не сводится к равенству значений в колонках: нужно сравнение «больше», «меньше», проверка по подстроке, комбинация условий «ИЛИ» или обращение к связанным данным через точку от ссылки.

Для Каждого СтрокаТовара Из Объект.Товары Цикл

Если СтрокаТовара.Количество > 100

Или СтрокаТовара.Сумма > 50000 Тогда

// Строка подходит под условие

Сообщить("Строка " + СтрокаТовара.НомерСтроки + ": превышение лимита");

КонецЕсли;

КонецЦикла;

Для поиска по подстроке используется функция СтрНайти(): например, найти все строки, где наименование содержит слово «услуга». Учтите, что СтрНайти() чувствительна к регистру — при необходимости приводите обе строки к одному регистру через ВРег() или НРег().

Если внутри цикла нужно удалять найденные строки, не удаляйте их прямо в цикле Для Каждого — это нарушит обход коллекции. Соберите строки в массив, а после цикла пройдите по массиву и вызовите Объект.Товары.Удалить(СтрокаТовара) для каждой.

Поиск в форме: особенности управляемых форм

В управляемой форме код может выполняться на клиенте или на сервере. Методы Найти() и НайтиСтроки() доступны в обоих контекстах, так как табличная часть объекта в форме представлена коллекцией данных формы. Это позволяет, например, проверять дубли при вводе строки без обращения к серверу.

Пример проверки дубля при изменении номенклатуры в строке:

&НаКлиенте

Процедура ТоварыНоменклатураПриИзменении(Элемент)

ТекущиеДанные = Элементы.Товары.ТекущиеДанные;

Отбор = Новый Структура("Номенклатура", ТекущиеДанные.Номенклатура);

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

Если НайденныеСтроки.Количество() > 1 Тогда

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

КонецЕсли;

КонецПроцедуры

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

В обычных формах (толстый клиент) синтаксис идентичен, но доступ к данным идёт напрямую к объекту. Различия касаются в основном оформления обработчиков событий, а не самих методов поиска.

Как проверить результат и отладить поиск

Главный признак корректной работы поиска — предсказуемый результат на контрольных данных. Перед внедрением кода проверьте три сценария: значение есть в табличной части (одна строка), значение есть в нескольких строках, значения нет вообще. Каждый сценарий должен отработать без ошибок и с ожидаемым результатом.

Для отладки используйте точки останова в конфигураторе: поставьте останов на строке вызова Найти() и посмотрите в табло, что вернул метод. Если вернулось Неопределено, хотя значение визуально присутствует, проверьте типы данных: сравните ТипЗнч(СтрокаТовара.Номенклатура) и тип искомого значения.

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

Контрольные точки

Как проверить результат

Возвращаемое значение Найти()
Норма

Строка табличной части, доступ к колонкам работает

Тревожный признак

Неопределено при том, что значение визуально есть — проверяйте типы

Массив от НайтиСтроки()
Норма

Количество элементов соответствует числу совпадений

Тревожный признак

Пустой массив или лишние строки — проверьте структуру отбора

Типы сравниваемых значений
Норма

Тип искомого значения совпадает с типом колонки

Тревожный признак

Строка вместо ссылки, строка вместо числа — совпадений не будет

Поведение при отсутствии результата
Норма

Код обрабатывает Неопределено и пустой массив без ошибок

Тревожный признак

Ошибка «Поле объекта не обнаружено» при пустом результате

Типичные ошибки и ограничения методов

Самая распространённая ошибка — обращение к колонке результата без проверки на Неопределено. Конструкция Объект.Товары.Найти(Товар, "Номенклатура").Количество упадёт с ошибкой, если товара нет в табличной части. Сначала сохраните результат в переменную, потом проверяйте.

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

Третья типичная проблема — ожидание, что НайтиСтроки() вернёт Неопределено при пустом результате. На самом деле возвращается пустой массив, и проверка Если НайденныеСтроки = Неопределено никогда не сработает. Правильная проверка — НайденныеСтроки.Количество() = 0.

Из ограничений стоит помнить: поиск по нескольким значениям одной колонки (условие «в списке») методами Найти() и НайтиСтроки() не поддерживается. Для таких задач нужен цикл с проверкой через массив (МассивЗначений.Найти(Значение) <> Неопределено) или запрос.

Типичные ошибки
01
Обращение к результату Найти() без проверки на Неопределено — ошибка выполнения при отсутствии строки
02
Проверка результата НайтиСтроки() на Неопределено вместо Количество() = 0 — условие никогда не срабатывает
03
Несовпадение типов: поиск строки в колонке со ссылкой — пустой результат без ошибки
04
Удаление строк внутри цикла Для Каждого — пропуск строк или сбой обхода коллекции
05
Опечатка в имени колонки в строке отбора — ошибка «Колонка не найдена» только в момент выполнения
Маршрут решения

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

Нужна одна строка по точному значению одной колонкиИспользуйте Найти() с проверкой на Неопределено
Нужны все строки с совпадением или отбор по нескольким колонкамИспользуйте НайтиСтроки() со структурой отбора
Условие сложное: «ИЛИ», сравнение больше/меньше, поиск по подстрокеПеребирайте строки в цикле Для Каждого с проверкой условия
Нужны итоги, группировка или соединение с другими даннымиВыгрузите табличную часть и выполните запрос на сервере

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

Чем Найти() отличается от НайтиСтроки()?

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

Почему Найти() возвращает Неопределено, хотя значение в табличной части есть?

Почти всегда причина в несовпадении типов: например, в колонке хранится ссылка на справочник, а ищется строка с наименованием. Проверьте тип колонки в конфигураторе и тип искомого значения через ТипЗнч(). Также убедитесь, что имя колонки указано без опечаток.

Как найти строку по нескольким значениям одной колонки?

Штатные методы этого не поддерживают. Сформируйте массив допустимых значений и перебирайте строки в цикле, проверяя МассивЗначений.Найти(СтрокаТовара.Номенклатура) <> Неопределено. Альтернатива — выгрузить табличную часть в запрос с условием В (&СписокЗначений).

Работают ли эти методы на клиенте в управляемой форме?

Да, оба метода доступны и на клиенте, и на сервере, поскольку табличная часть объекта в форме представлена коллекцией данных формы. Это позволяет проверять дубли и искать строки без серверных вызовов, что ускоряет отклик формы.

Как удалить все найденные строки?

Получите массив через НайтиСтроки(), затем в цикле по этому массиву вызовите Объект.Товары.Удалить(СтрокаМассива) для каждой строки. Не удаляйте строки внутри цикла Для Каждого по самой табличной части — это нарушает обход коллекции.

Можно ли искать в табличной части запросом?

Напрямую к табличной части в запросе обратиться нельзя, но её можно передать в запрос как временную таблицу: поместить Объект.Товары.Выгрузить() в параметр и использовать пакетный запрос с конструкцией ПОМЕСТИТЬ. Это оправдано при группировках, итогах и соединениях с другими таблицами.

Итог

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

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