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