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

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

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

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

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

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

Основной принцип: сначала строка, потом реквизит

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

// Получаем первую строку табличной части "Товары"

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

// Теперь читаем или меняем реквизиты строки

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

СтрокаТЧ.Цена = 1500;

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

Индексация строк начинается с нуля: Товары[0] — первая строка, Товары[1] — вторая. Количество строк возвращает метод Количество(): ДокументОбъект.Товары.Количество(). Если табличная часть пустая, обращение по индексу вызовет ошибку, поэтому перед прямым доступом проверяйте, что строки есть.

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

Обращение к реквизиту в обработчиках управляемой формы

В управляемой форме документа данные табличной части хранятся в реквизите формы (обычно Объект.Товары), а текущая редактируемая строка доступна через элемент формы. Для табличной части на форме стандартный способ получить активную строку — свойство ТекущиеДанные элемента формы:

&НаКлиенте

Процедура ТоварыПриИзменении(Элемент)

ТекущиеДанные = Элементы.Товары.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

Возврат;

КонецЕсли;

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

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

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

Обход всех строк на форме

Для перебора всех строк табличной части на форме используется цикл:

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

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

СтрокаТЧ.Сумма = 0;

КонецЕсли;

КонецЦикла;

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

В управляемых формах у каждой строки есть уникальный идентификатор ПолучитьИдентификатор(). Если вы сохранили его ранее, строку можно найти методом НайтиПоИдентификатору():

СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);

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

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

КонецЕсли;

Обращение к реквизиту табличной части на сервере и в модуле объекта

В модуле объекта, в серверных процедурах или при программном создании документа работа идёт напрямую с объектом. Добавление строки и заполнение реквизитов выглядит так:

НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДокумент.Дата = ТекущаяДатаСеанса();

НоваяСтрока = НовыйДокумент.Товары.Добавить();

НоваяСтрока.Номенклатура = НайденныйТовар;

НоваяСтрока.Количество = 5;

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

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

НовыйДокумент.Записать();

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

Для чтения данных из уже записанного документа сначала получите объект через ссылку:

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

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

Сообщить("Товар: " + СтрокаТЧ.Номенклатура + ", сумма: " + СтрокаТЧ.Сумма);

КонецЦикла;

Получение данных табличной части без объекта: запрос и обращение через ссылку

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

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

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

"ВЫБРАТЬ

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

| Товары.Количество КАК Количество,

| Товары.Сумма КАК Сумма

|ИЗ

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

|ГДЕ

| Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

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

КонецЦикла;

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

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

Через объект (ПолучитьОбъект)

Подходит, когда данные нужно изменить и записать. Дорого по ресурсам, блокирует объект.

Запрос к табличной части

Оптимально для чтения, отборов и агрегации. Нельзя менять данные напрямую.

ТекущиеДанные на форме

Единственный корректный способ в клиентских обработчиках управляемой формы.

Через ссылку (Ссылка.Товары)

Быстро для разового чтения, но генерирует отдельное обращение к БД при каждом вызове.

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

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

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

Если НайденнаяСтрока = Неопределено Тогда

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

НоваяСтрока.Номенклатура = ИскомыйТовар;

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

Иначе

НайденнаяСтрока.Количество = НайденнаяСтрока.Количество + 1;

КонецЕсли;

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

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

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

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

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

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

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

КонецЦикла;

Типовой порядок работы с реквизитом табличной части
  1. 1
    Определите контекст: форма, модуль объекта или внешний код
  2. 2
    Получите строку: по индексу, через ТекущиеДанные, Найти() или циклом
  3. 3
    Проверьте, что строка найдена (не Неопределено) и табличная часть не пуста
  4. 4
    Прочитайте или измените реквизит через точку: Строка.ИмяРеквизита
  5. 5
    При изменениях на сервере — запишите объект, на форме — при необходимости установите Модифицированность
  6. 6
    Проверьте результат: откройте форму документа и убедитесь, что значения корректны

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

Большинство проблем при работе с табличными частями связано с неправильным контекстом исполнения или отсутствием проверок. Разберём самые частые сценарии сбоев.

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

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

Проверка результата и ограничения

После изменения реквизитов табличной части убедитесь, что изменения сохранились: для объекта — вызовите Записать() и перечитайте данные запросом, для формы — проверьте визуально значения в таблице и признак модифицированности. Если документ проводится, помните: пересчёт связанных реквизитов (например, суммы по ставке НДС) в типовых конфигурациях часто выполняется в обработчиках формы, и программное изменение строки вне формы этих обработчиков не вызовет — пересчитывайте зависимые реквизиты самостоятельно.

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

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

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

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

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

Возвращается старое значение — объект не был записан или изменялась другая строка

Работа обработчика формы
Норма

При изменении строки пересчитываются зависимые реквизиты без ошибок

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

Ошибка при входе в обработчик — нет проверки ТекущиеДанные на Неопределено

Итоговые суммы документа
Норма

Суммы по строкам совпадают с итогами и движениями документа

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

Итоги расходятся — зависимые реквизиты не пересчитаны программно

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

Итог

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

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

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

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

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

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

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

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

Да, через квадратные скобки: СтрокаТЧ["Количество"]. Это удобно, когда имя реквизита формируется динамически, например при универсальной обработке разных табличных частей. Если реквизита с таким именем нет, возникнет ошибка.

Почему изменение реквизита строки не сохраняется после закрытия формы?

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

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

Используйте метод Очистить(): ДокументОбъект.Товары.Очистить(). Для выборочного удаления соберите строки через НайтиСтроки() в массив и удаляйте каждую методом Удалить(СтрокаТЧ) — удаление прямо внутри цикла перебора коллекции приводит к пропуску элементов.

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

У строки есть свойство НомерСтроки (нумерация с единицы): СтрокаТЧ.НомерСтроки. Индекс строки в коллекции можно получить методом Индекс(): ДокументОбъект.Товары.Индекс(СтрокаТЧ) — он на единицу меньше номера строки, так как индексация идёт с нуля.