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