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

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

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

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

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

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

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

Что нужно понимать о структуре табличной части на форме

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

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

Обращение к реквизиту текущей строки

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

&НаКлиенте

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

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

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

Возврат;

КонецЕсли;

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

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

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

Чтение значения выполняется так же: ТекЦена = Элементы.Товары.ТекущиеДанные.Цена;. Если нужен реквизит, которого нет в колонках таблицы на форме, но он есть в табличной части объекта, он всё равно доступен через ТекущиеДанные — достаточно, чтобы реквизит присутствовал в данных, связанных с таблицей.

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

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

&НаКлиенте

Процедура ПересчитатьИтоги(Команда)

ИтогоСумма = 0;

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

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

ИтогоСумма = ИтогоСумма + СтрокаТовара.Сумма;

КонецЦикла;

ИтогоПоДокументу = ИтогоСумма;

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

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

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

Поиск строки по условию

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

Отбор = Новый Структура("Номенклатура", ВыбраннаяНоменклатура);

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

Если НайденныеСтроки.Количество() > 0 Тогда

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

КонецЕсли;

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

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

// Текущая строка

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

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

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

КонецЕсли;

// Перебор всех строк

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

// обработка

КонецЦикла;

В модуле обычной формы документа коллекция табличной части доступна просто по имени — Товары, без префикса Объект. Это частая причина путаницы при переносе кода из обычной формы в управляемую: там тот же цикл потребует Объект.Товары.

Обращение из модуля объекта и извне формы

В модуле объекта документа (обработчики ОбработкаПроведения, ПередЗаписью и другие) табличная часть доступна напрямую по имени: Товары.Итог("Сумма"), Товары[0].Цена. Никаких Элементы и ТекущиеДанные здесь нет — модуль объекта работает только с данными, а не с формой.

Из внешнего кода (другой документ, обработка, регламентное задание) обращение идёт через объектную ссылку: ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект(); Цена = ДокументОбъект.Товары[0].Цена;. Либо запросом, если нужно только чтение — это быстрее и не блокирует объект:

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

Запрос.Текст = "ВЫБРАТЬ Товары.Цена, Товары.Количество

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

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

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

Способы обращения

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

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

Объект.Товары[i].Цена

Форма, любая строка по индексу или в цикле. Подходит для пересчётов и проверок всех строк.

Товары[i].Цена в модуле объекта

Серверный контекст объекта, проведение и запись. Не работает на форме.

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

Только чтение из базы. Не видит несохранённые изменения открытой формы.

Типичные ошибки и ограничения

Первая группа ошибок связана с контекстом выполнения. На клиенте управляемой формы нельзя использовать запросы и методы работы с базой — попытка выполнить Новый Запрос в клиентской процедуре приведёт к ошибке компиляции. Выносите такую логику в серверные процедуры, а на клиент передавайте только результат.

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

Третья типичная ситуация — изменение реквизита через ТекущиеДанные не вызывает пересчёт зависимых данных, потому что обработчики ПриИзменении не срабатывают при программном изменении. Если вы программно установили цену, вызовите пересчёт суммы явно в том же коде.

Типичные ошибки
01
Обращение ТекущиеДанные.Цена без проверки на Неопределено — ошибка при пустой таблице
02
Использование Элементы.ИмяТабличнойЧасти, когда элемент формы переименован — возвращается Неопределено
03
Попытка выполнить запрос к базе в клиентской процедуре — ошибка компиляции, нужна серверная процедура
04
Ожидание, что программное изменение реквизита вызовет обработчик ПриИзменении — он не вызывается, пересчёт нужно делать вручную
05
Перенос кода Товары.Итог() из обычной формы в управляемую без префикса Объект

Как проверить, что код работает правильно

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

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

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

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

Пустая табличная часть
Норма

Обработчики завершаются без ошибок

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

Ошибка «Поле объекта не обнаружено» или обращение к Неопределено

Изменение значения в строке
Норма

Зависимые реквизиты пересчитываются

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

Сумма остаётся старой после смены цены

Имя элемента формы
Норма

Элементы.Имя возвращает таблицу, ТекущиеДанные доступны

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

Элементы.Имя возвращает Неопределено — имя не совпадает

Клиентский вызов
Норма

Запросы и работа с базой только в серверных процедурах

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

Ошибка компиляции на клиенте

Итог

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

Текущая строка — через Элементы.ИмяТаблицы.ТекущиеДанные с обязательной проверкой на Неопределено. Все строки — через коллекцию Объект.ИмяТабличнойЧасти. В модуле объекта табличная часть доступна просто по имени. Работа с базой данных — только на сервере.

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

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

Используйте свойство НомерСтроки: Номер = Элементы.Товары.ТекущиеДанные.НомерСтроки;. Нумерация в этом свойстве начинается с единицы, тогда как индекс в коллекции Объект.Товары — с нуля, поэтому соответствующий индекс равен НомерСтроки - 1.

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

Для программно добавленной таблицы обращение идёт по имени, заданному при создании элемента: Элементы["МояТаблица"].ТекущиеДанные. Главное условие — у элемента должен быть корректно заполнен ПутьКДанным, иначе ТекущиеДанные будет пустым.

Почему ТекущиеДанные возвращает Неопределено, хотя строки в таблице есть?

ТекущиеДанные отражает активную строку, а не просто наличие строк. Если таблица не имеет фокуса или текущая строка не установлена, свойство равно Неопределено. Установить текущую строку программно можно через Элементы.Товары.ТекущаяСтрока = Объект.Товары[0].ПолучитьИдентификатор();.

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

Переберите коллекцию ВыделенныеСтроки элемента формы и по каждому идентификатору получите строку данных: Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл Строка = Объект.Товары.НайтиПоИдентификатору(Ид); Строка.СтавкаНДС = НовоеЗначение; КонецЦикла;.

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

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

Чем отличается Итог() табличной части от суммирования в цикле?

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