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

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

Как перебрать все строки в табличном поле 1С

Как перебрать строки табличного поля в 1С: обход табличной части, ДанныеФормыКоллекция, выделенные строки, поиск и итоги. Примеры кода для управляемых и обычных форм.

Перебор строк табличного поля — одна из самых частых задач при доработке форм в 1С. Важно понимать ключевой момент: табличное поле — это лишь элемент отображения, а сами данные хранятся в реквизите формы или в табличной части объекта. Поэтому обход выполняется не по «строкам на экране», а по коллекции данных, к которой привязано табличное поле.

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

Что перебирать: табличное поле или данные за ним

Табличное поле (элемент формы) отвечает только за визуализацию: колонки, оформление, выделение. Реальные строки лежат в источнике данных — табличной части документа, реквизите формы типа «ТаблицаЗначений» (ДанныеФормыКоллекция) или динамическом списке. Попытка «пройтись по табличному полю» напрямую приведёт к ошибке, потому что у элемента формы нет коллекции строк в привычном смысле.

Правильный подход — определить, что указано в свойстве «ПутьКДанным» табличного поля, и работать с этой коллекцией. Например, если путь к данным — «Объект.Товары», перебираем Объект.Товары. Если это реквизит формы «СписокНоменклатуры» типа «Таблица значений», перебираем его.

Перебор табличной части объекта в управляемой форме

Самый типовой сценарий — обход табличной части документа или справочника. Код одинаково работает на клиенте и на сервере, так как данные объекта доступны в обоих контекстах:

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

СуммаСтроки = СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;

// обработка строки

КонецЦикла;

Если нужен номер строки, он доступен через свойство НомерСтроки (нумерация с единицы). Для обращения по индексу используйте цикл Для Индекс = 0 По Объект.Товары.Количество() - 1 Цикл — индексация коллекции начинается с нуля. Это частая причина путаницы: НомерСтроки на единицу больше индекса.

Пример с обращением по индексу, когда нужно сравнить текущую строку с предыдущей:

Для Индекс = 0 По Объект.Товары.Количество() - 1 Цикл

ТекущаяСтрока = Объект.Товары[Индекс];

Если Индекс > 0 Тогда

ПредыдущаяСтрока = Объект.Товары[Индекс - 1];

КонецЕсли;

КонецЦикла;

Перебор реквизита формы типа «Таблица значений»

Если табличное поле привязано к реквизиту формы, в управляемой форме он представлен объектом ДанныеФормыКоллекция. Перебор выглядит аналогично:

Для Каждого СтрокаТаблицы Из СписокНоменклатуры Цикл

// СписокНоменклатуры — реквизит формы (ТаблицаЗначений)

Если СтрокаТаблицы.Пометка Тогда

// обработка отмеченных

КонецЕсли;

КонецЦикла;

Нюанс: строки ДанныеФормыКоллекция на клиенте доступны только для чтения по части свойств в некоторых контекстах, а серверные методы вроде Выгрузить() требуют серверного вызова. Если нужно массово обработать данные запросом, выгрузите коллекцию в таблицу значений на сервере: ТаблицаРезультат = РеквизитФормыВЗначение("СписокНоменклатуры");.

Перебор только выделенных пользователем строк

Когда обработать нужно не всю таблицу, а строки, которые пользователь выделил вручную, используется свойство ВыделенныеСтроки элемента формы. Оно содержит массив идентификаторов строк, а не сами строки:

Для Каждого ИдентификаторСтроки Из Элементы.Товары.ВыделенныеСтроки Цикл

СтрокаТаблицы = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);

Если СтрокаТаблицы <> Неопределено Тогда

// обработка строки

КонецЕсли;

КонецЦикла;

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

Порядок действий при обработке выделенных строк
  1. 1
    Определите имя табличного поля и его путь к данным
  2. 2
    На клиенте получите массив Элементы.ИмяТаблицы.ВыделенныеСтроки
  3. 3
    Проверьте, что массив не пустой, иначе сообщите пользователю
  4. 4
    Для каждого идентификатора получите строку через НайтиПоИдентификатору
  5. 5
    Выполните обработку и при необходимости обновите итоги на форме

Поиск строк по условию вместо полного перебора

Если задача — найти строки с определённым значением, полный перебор с ветвлением Если избыточен. Коллекции поддерживают метод НайтиСтроки, который возвращает массив подходящих строк:

Отбор = Новый Структура("Номенклатура", ИскомаяНоменклатура);

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

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

// обработка найденных строк

КонецЦикла;

Метод работает и на клиенте, и на сервере, выполняется быстрее ручного цикла и делает код читаемее. Для подсчёта суммы по колонке без перебора используйте Объект.Товары.Итог("Сумма") — это стандартный способ получения итогов табличной части.

Сравнение вариантов обхода

Для Каждого по коллекции

Универсальный полный перебор всех строк. Подходит, когда обработать нужно каждую строку.

НайтиСтроки с отбором

Быстрый поиск по равенству одного или нескольких полей. Не поддерживает условия вида «больше», «содержит».

Выгрузить() + запрос

Для сложных условий, группировок и соединений на сервере. Требует серверного вызова и избыточен для малых таблиц.

ВыделенныеСтроки

Только строки, отмеченные пользователем. Работает лишь на клиенте, требует НайтиПоИдентификатору.

Перебор в обычных формах и на сервере вне формы

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

ТаблицаДанных = ЭлементыФормы.ТабличноеПоле1.Значение;

Для Каждого СтрокаТаблицы Из ТаблицаДанных Цикл

// обработка

КонецЦикла;

Вне формы — в модуле объекта, менеджере или внешней обработке — табличное поле недоступно в принципе, и перебирается только табличная часть объекта: Для Каждого СтрокаТаблицы Из ДокументОбъект.Товары Цикл. Если обработка выполняется по ссылке, сначала получите объект методом ПолучитьОбъект(), а после изменений вызовите Записать().

Типичные ошибки
01
Перебор Элементы.Товары вместо Объект.Товары — элемент формы не содержит данных строк, код падает с ошибкой
02
Смешение индекса и НомерСтроки: индекс начинается с 0, номер строки — с 1, смещение даёт обработку не той строки
03
Удаление строк внутри цикла Для Каждого — часть строк пропускается, результат непредсказуем
04
Обращение к ВыделенныеСтроки на сервере — свойство доступно только на клиенте
05
Медленный перебор с серверными вызовами внутри цикла на клиенте — каждая итерация гоняет вызов на сервер, форма зависает

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

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

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

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

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

Число обработанных строк
Норма

Совпадает с количеством строк в коллекции или в выборке

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

Меньше ожидаемого — вероятен пропуск строк при удалении в цикле

Итоги на форме
Норма

Пересчитаны и отображают актуальные суммы

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

Итоги устарели — не вызван пересчёт после изменения

Модифицированность
Норма

После изменения данных объект помечен как изменённый

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

Изменения есть, а признак не установлен — данные можно потерять при закрытии

Часто задаваемые вопросы

Итог

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

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

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

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

Как получить текущую строку табличного поля?

Используйте Элементы.ИмяТаблицы.ТекущаяСтрока — это идентификатор строки. Затем получите данные: Объект.Товары.НайтиПоИдентификатору(Элементы.Товары.ТекущаяСтрока). Проверяйте, что ТекущаяСтрока не равна Неопределено, иначе таблица пуста.

Можно ли перебирать строки в цикле Пока?

Да, через индекс: Индекс = 0; Пока Индекс < Объект.Товары.Количество() Цикл ... Индекс = Индекс + 1; КонецЦикла. Такой вариант удобен, когда внутри цикла нужно управлять переходом, например пропускать или удалять строки с корректировкой индекса.

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

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

Почему перебор работает на клиенте, но падает на сервере?

Чаще всего код обращается к Элементы.ИмяТаблицы или к ВыделенныеСтроки — они существуют только в клиентском контексте. Перенесите получение идентификаторов на клиент, а серверной процедуре передавайте массив идентификаторов или сами данные параметром.

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

Используйте метод Итог: Объект.Товары.Итог("Сумма"). Он работает и на клиенте, и на сервере, не требует цикла и выполняется быстрее ручного накопления в переменной.