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

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

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

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

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

Работа с табличной частью на сервере и на клиенте отличается: в управляемых формах на клиенте доступна только ДанныеФормыКоллекция, где часть серверных методов отсутствует. Это частая причина ошибок «Метод объекта не обнаружен» при переносе кода из модуля объекта в модуль формы.

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

Что такое объект табличной части и где он хранится

Табличная часть — реквизит составного типа у документа, справочника, обработки или другого объекта конфигурации. В модуле объекта (например, документа «РеализацияТоваровУслуг») доступ к ней выполняется напрямую по имени: Товары или ЭтотОбъект.Товары. Тип значения — ТабличнаяЧасть, коллекция строк типа ТабличнаяЧастьСтрока.

Если у вас есть ссылка на документ, а не объект, сначала нужно получить объект методом ПолучитьОбъект(), и только после этого обращаться к табличной части:

ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

ТабЧасть = ДокОбъект.Товары;

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

Базовое обращение к табличной части через точку

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

// В модуле объекта документа

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

Сообщить(СтрокаТЧ.Номенклатура);

КонецЦикла;

// Через ссылку из произвольного кода

ДокОбъект = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("0001", ТекущаяДата()).ПолучитьОбъект();

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

Отдельная строка по индексу получается через квадратные скобки или метод Получить(). Индексация начинается с нуля, поэтому последняя строка имеет индекс Количество() - 1. Обращение за границы диапазона вызовет ошибку выполнения, поэтому перед доступом по индексу проверяйте количество строк.

Если ДокОбъект.Товары.Количество() > 0 Тогда

ПерваяСтрока = ДокОбъект.Товары[0];

// или: ДокОбъект.Товары.Получить(0);

КонецЕсли;

Поиск строк: Найти и НайтиСтроки

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

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

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

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

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

КонецЕсли;

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

Метод НайтиСтроки — отбор по нескольким условиям

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

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

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

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

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

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

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

КонецЦикла;

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

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

Особенности работы в управляемой форме

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

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

&НаСервере

Процедура ПересчитатьНаСервере()

ДокОбъект = РеквизитФормыВЗначение("Объект");

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

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

КонецЦикла;

ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

Также в форме полезна Элементы.Товары.ТекущиеДанные — это текущая строка табличного поля, выбранная пользователем. Через неё в обработчиках событий (ПриИзменении, ПередУдалением) получают данные активной строки без поиска.

Сравнение способов доступа

Обращение через точку (Объект.Товары)

Универсальный способ. В модуле объекта даёт ТабличнаяЧасть, в форме — ДанныеФормыКоллекция с ограниченным набором методов

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

Поиск по равенству значений. Быстро и читаемо, но не поддерживает сложные условия

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

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

Выгрузить() в таблицу значений

Удобен для сложных отборов и сортировок, доступен только на сервере, создаёт копию данных

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

Наиболее частая ошибка — обращение к табличной части по ссылке без получения объекта. У ссылки (ДокументСсылка) табличная часть доступна только для чтения через точку, и попытка её изменить закончится ошибкой. Для изменений всегда вызывайте ПолучитьОбъект() и не забывайте Записать() после правок.

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

// Удаление с конца коллекции

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

СтрокаТовара = ДокОбъект.Товары[ДокОбъект.Товары.Количество() - Инд];

Если СтрокаТовара.Количество = 0 Тогда

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

КонецЕсли;

КонецЦикла;

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

Типичные ошибки
01
Изменение табличной части через ссылку без ПолучитьОбъект() — изменения не сохранятся или возникнет ошибка
02
Обращение к результату Найти() без проверки на Неопределено — ошибка «Поле объекта не обнаружено»
03
Удаление строк в прямом цикле перебора — пропуск строк из-за сдвига индексов
04
Вызов серверных методов (Выгрузить, Загрузить) на клиенте в управляемой форме — «Метод объекта не обнаружен»
05
Опечатка в имени колонки структуры отбора — ошибка выполнения НайтиСтроки

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

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

После изменений и записи объекта проверьте результат чтением из базы: перечитайте документ и сравните содержимое табличной части. Это защищает от ситуации, когда изменения выполнялись в копии объекта и не попали в базу из-за пропущенного Записать().

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

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

Количество строк после операции
Норма

Совпадает с ожидаемым числом

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

Строк меньше или больше — проверьте условия отбора и удаления

Результат Найти()
Норма

Возвращена строка, реквизиты доступны

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

Неопределено — значение или имя колонки не совпадают с данными

Данные в базе после Записать()
Норма

Перечитанный объект содержит изменения

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

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

Когда нужна альтернатива: запрос к табличной части

Если нужно получить строки табличных частей сразу многих документов или соединить их с другими данными, перебор объектов в цикле неэффективен. В этом случае используют запрос к табличной части через точку в тексте запроса: Документ.РеализацияТоваровУслуг.Товары — это виртуальная таблица, доступная в конструкторе запросов.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Номенклатура,

| СУММА(Товары.Количество) КАК Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка.Дата МЕЖДУ &Начало И &Конец

|СГРУППИРОВАТЬ ПО

| Товары.Номенклатура";

Запрос не даёт объекта табличной части для изменения — он возвращает выборку только для чтения. Но для отчётов, свёрток и анализа это правильный и быстрый инструмент, тогда как ПолучитьОбъект() в цикле по тысячам документов создаст серьёзную нагрузку.

Если в управляемой форме нужно только пересчитать пару реквизитов строки, делайте это на клиенте через Элементы.Товары.ТекущиеДанные — без вызова сервера. Вызов серверной процедуры на каждое изменение строки заметно замедляет работу пользователя при слабом канале связи.
ПЗ
Практическое замечание

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

Как получить табличную часть, не открывая объект целиком?

Для чтения табличная часть доступна прямо через ссылку: Ссылка.Товары вернёт строки в режиме чтения. Для чтения большого числа документов эффективнее запрос к виртуальной таблице Документ.ИмяДокумента.ИмяТабличнойЧасти.

Почему НайтиСтроки возвращает пустой массив, хотя строка есть?

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

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

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

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

Да, через квадратные скобки: ДокОбъект["Товары"] или Объект[ИмяТабличнойЧасти]. Это удобно в универсальных обработках, где имя табличной части хранится в переменной. Метаданные помогут узнать список табличных частей: Объект.Метаданные().ТабличныеЧасти.

Чем отличается Выгрузить() от прямого перебора?

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

Итог

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

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