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

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

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

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

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

Базовый принцип прост: табличная часть доступна как свойство объекта по её имени, а конкретная строка — по индексу (нумерация с нуля) или через перебор коллекции. Например, ДокументОбъект.Товары[0].Номенклатура вернёт значение реквизита «Номенклатура» из первой строки табличной части «Товары».

Ошибки чаще всего возникают из-за путаницы между объектными данными и данными формы, обращения по несуществующему индексу и попыток изменить строку, полученную «на чтение». Ниже разобраны все основные способы с примерами и границами применения.

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

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

СтрокаТЧ = ДокументОбъект.Товары[0];

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

Перед обращением по индексу всегда проверяйте, что строка существует. Если табличная часть пуста, обращение Товары[0] вызовет ошибку выполнения. Безопасный вариант — проверка через метод Количество():

Если ДокументОбъект.Товары.Количество() > 0 Тогда
  ПерваяСтрока = ДокументОбъект.Товары[0];
КонецЕсли;

Перебор всех строк табличной части

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

Для Каждого СтрокаТовара Из ДокументОбъект.Товары Цикл
  СтрокаТовара.Сумма = СтрокаТовара.Количество * СтрокаТовара.Цена;
КонецЦикла;

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

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

Для Сч = 1 По ДокументОбъект.Товары.Количество() Цикл
  Индекс = ДокументОбъект.Товары.Количество() - Сч;
  Если УсловиеУдаления Тогда
    ДокументОбъект.Товары.Удалить(Индекс);
  КонецЕсли;
КонецЦикла;

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

Поиск строки по значению реквизита

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

СтрокаНайденная = ДокументОбъект.Товары.Найти(НужнаяНоменклатура, "Номенклатура");
Если СтрокаНайденная <> Неопределено Тогда
  СтрокаНайденная.Количество = СтрокаНайденная.Количество + 1;
КонецЕсли;

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

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

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

Текущая строка табличной части на форме

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

СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
Если СтрокаТаблицы <> Неопределено Тогда
  СтрокаТаблицы.Сумма = СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;
КонецЕсли;

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

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

Различия контекстов: модуль объекта, форма, внешний код

Один и тот же смысл «обратиться к строке» записывается по-разному в зависимости от того, где выполняется код. Путаница между контекстами — типичный источник ошибок компиляции и выполнения.

КонтекстКак обратиться к строкеОсобенность
Модуль объектаТовары[0] или ЭтотОбъект.Товары[0]Данные доступны напрямую, без ЭтотОбъект тоже работает
Модуль формыОбъект.Товары[0]Объект — реквизит формы с данными документа
Текущая строка на формеЭлементы.Товары.ТекущиеДанныеМожет быть Неопределено, проверка обязательна
Внешний код по ссылкеСсылка.Товары[0]Только чтение; для изменения нужен ПолучитьОбъект()

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

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

Первая группа ошибок связана с индексами: разработчик забывает, что индексация начинается с нуля, и обращается к Товары[Товары.Количество()], получая исключение. Последний допустимый индекс — Количество() - 1.

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

Ещё одна частая ситуация — обращение к табличной части по имени, записанному строкой: Объект["Товары"]. Такой синтаксис работает, но лишает вас проверки конфигуратором: опечатка в имени проявится только в момент выполнения. Используйте строковое обращение только когда имя табличной части действительно вычисляется динамически.

Типичные ошибки
01
Обращение к Товары[0] без проверки Количества() — исключение на пустой табличной части
02
Изменение строки, полученной через ссылку — ошибка, данные доступны только на чтение
03
Поиск через Найти() строкой вместо ссылки — результат всегда Неопределено
04
Удаление строк внутри цикла Для Каждого — пропуск строк или ошибка обхода коллекции
05
Использование Элементы.Товары.ТекущиеДанные без проверки на Неопределено

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

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

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

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

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

Значение реквизита строки после присваивания
Норма

Сообщить(СтрокаТЧ.Сумма) выводит новое значение

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

Значение старое — изменялась копия, а не строка коллекции

Сохранение в базе
Норма

После Записать() документ в списке показывает новые данные

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

Данные не изменились — объект не был записан

Работа поиска
Норма

Найти() вернул строку с нужным значением

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

Возвращает Неопределено — проверьте тип значения отбора

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

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

Используйте метод Количество(): ДокументОбъект.Товары.Количество(). Метод возвращает целое число; для пустой табличной части — ноль. Это стандартная проверка перед обращением к строкам по индексу.

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

Индекс используется в коде и начинается с нуля: Товары[0] — первая строка. НомерСтроки — свойство строки, которое видит пользователь, и начинается с единицы. Для первой строки индекс равен 0, а НомерСтроки равен 1.

Можно ли обратиться к табличной части, не зная её имени заранее?

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

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

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

Как обратиться к строке табличной части в запросе?

В запросе табличная часть — отдельная виртуальная таблица: ВЫБРАТЬ Товары.Номенклатура ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Товары ГДЕ Товары.Ссылка = &Ссылка. Обращение по индексу в запросе недоступно, используется отбор по ссылке и условиям.

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

Вызовите метод Добавить(): НоваяСтрока = ДокументОбъект.Товары.Добавить(); затем заполните реквизиты: НоваяСтрока.Номенклатура = Товар; НоваяСтрока.Количество = 1; После этого запишите объект, чтобы изменения сохранились в базе.

Итог

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

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