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

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

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

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

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

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

Что представляет собой коллекция строк табличной части

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

Важно понимать разницу между данными объекта и данными формы. В управляемой форме табличная часть отображается через реквизит формы типа «ДанныеФормыКоллекция», и работа со строками на клиенте идёт именно с этой структурой. Методы НайтиСтроки и Выгрузить доступны в обоих случаях, но типы возвращаемых строк различаются.

Перебор всех строк в цикле

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

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

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

СтрокаТовара.Сумма = СуммаСтроки;

КонецЦикла;

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

Если внутри цикла нужно удалять строки, обход «Для Каждого» небезопасен: коллекция изменяется во время итерации. В таком случае используют обратный обход по индексу, о котором сказано ниже, или собирают строки для удаления в отдельный массив и удаляют их после цикла.

Обращение к строке по индексу и номеру

Коллекция строк поддерживает индексированный доступ: Объект.Товары[0] вернёт первую строку. Индексация начинается с нуля, а количество строк определяется методом Количество(). Это позволяет организовать классический цикл со счётчиком.

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

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

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

КонецЦикла;

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

Обратный обход по индексу — стандартный приём при удалении строк по условию:

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

РеальныйИндекс = -Индекс;

Если Объект.Товары[РеальныйИндекс].Количество = 0 Тогда

Объект.Товары.Удалить(РеальныйИндекс);

КонецЕсли;

КонецЦикла;

Поиск строк по условию с помощью НайтиСтроки

Метод НайтиСтроки возвращает массив строк, удовлетворяющих отбору. Отбор задаётся структурой, где ключ — имя колонки, а значение — искомое значение. Сравнение выполняется на строгое равенство.

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

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

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

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

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

КонецЦикла;

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

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

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

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

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

Иначе

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

НоваяСтрока.Номенклатура = ИскомыйТовар;

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

КонецЕсли;

Порядок действий при поиске строк
  1. 1
    Сформируйте структуру отбора с именами колонок и значениями
  2. 2
    Вызовите НайтиСтроки(Отбор) или Найти(Значение, Колонка)
  3. 3
    Проверьте результат: массив пуст или строка равна Неопределено
  4. 4
    Обработайте найденные строки в цикле или добавьте новую при отсутствии

Выгрузка строк в таблицу значений

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

ТаблицаТоваров = Объект.Товары.Выгрузить();

ТаблицаТоваров.Свернуть("Номенклатура", "Количество,Сумма");

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

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

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

В управляемой форме табличная часть представлена реквизитом Объект типа «ДанныеФормыСтруктура», а сама коллекция — «ДанныеФормыКоллекция». На клиенте доступны перебор в цикле, НайтиСтроки, обращение по индексу, методы Добавить, Удалить, Итог. Этого достаточно для большинства интерактивных сценариев: пересчёта сумм, проверки дублей, заполнения по выбранному значению.

Для текущей выделенной строки в элементе формы используется свойство Элементы.Товары.ТекущиеДанные. Оно возвращает объект «ДанныеФормыЭлементКоллекции» с реквизитами строки, которую пользователь редактирует прямо сейчас. Через ТекущаяСтрока можно получить идентификатор строки и по нему найти её в коллекции методом НайтиПоИдентификатору.

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

Сравнение вариантов

Цикл Для Каждого

Подходит для полной обработки всех строк; небезопасен при удалении элементов внутри цикла

НайтиСтроки / Найти

Подходит для поиска по точному равенству; не поддерживает условия «больше», «содержит»

Выгрузить()

Подходит для группировки, сортировки и передачи в запрос; требует загрузки обратно и недоступен на клиенте формы

ТекущиеДанные элемента формы

Подходит для обработки редактируемой строки; работает только при наличии выделенной строки в таблице формы

Типичные ошибки и как их избежать

Одна из самых распространённых ошибок — обращение к строке по номеру вместо индекса. Конструкция Объект.Товары[1] вернёт вторую строку, а не первую, что приводит к смещению обработки и трудноуловимым дефектам. Всегда помните о нумерации с нуля.

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

Третья частая проблема — изменение коллекции во время обхода и забытая проверка результата поиска. Оба случая приводят к ошибкам исполнения, которые всплывают только на конкретных данных, поэтому закладывайте проверки сразу, а не после первого падения в рабочей базе.

Типичные ошибки
01
Обращение по НомерСтроки как по индексу — смещение на единицу и обработка не тех строк
02
Удаление строк внутри цикла Для Каждого — пропуск элементов или ошибка выхода за границы
03
Отсутствие проверки результата Найти() — ошибка при обращении к Неопределено
04
Вызов Выгрузить() на клиенте управляемой формы — метод недоступен в этом контексте
05
Забытый Загрузить() после обработки выгруженной таблицы — изменения не сохраняются

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

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

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

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

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

Количество обработанных строк
Норма

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

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

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

Результат НайтиСтроки
Норма

Массив содержит строки, поля соответствуют отбору

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

Пустой массив при заведомо существующих данных — проверить типы значений отбора

Изменения после обработки
Норма

Данные строк обновлены и видны в форме или после записи объекта

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

Изменения потеряны — не выполнен Загрузить() или обработана копия данных

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

Итог

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

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

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

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

Используйте свойство Элементы.Товары.ВыделенныеСтроки — оно возвращает массив идентификаторов строк. По каждому идентификатору получите строку через Объект.Товары.НайтиПоИдентификатору(Ид) и обработайте её.

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

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

Как найти строки по условию «больше» или «содержит»?

Методы НайтиСтроки и Найти поддерживают только строгое равенство. Для нестрогих условий перебирайте коллекцию в цикле с проверкой внутри, либо выгрузите данные в таблицу значений и используйте запрос с операторами сравнения и ПОДОБНО.

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

Да, табличные части доступны в запросах как виртуальные таблицы вида «Документ.РеализацияТоваровУслуг.Товары». Это эффективно для выборки строк по многим документам сразу, но для обработки строк одного открытого объекта проще работать с коллекцией напрямую.

Почему изменения строк на клиенте не видны после вызова серверной процедуры?

Серверная процедура работает со своей копией данных формы. Если в ней объект получали через РеквизитФормыВЗначение и модифицировали, верните изменения через ЗначениеВРеквизитФормы либо передайте результат обратно параметром и обновите коллекцию формы на клиенте.

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

Соберите подлежащие удалению строки в массив внутри обычного цикла обхода, затем во втором цикле вызовите Удалить для каждой собранной строки. Либо используйте обратный обход по индексу от последней строки к первой — тогда удаление не нарушает порядок итерации.