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