Почему возникает ошибка «Поле объекта не обнаружено (ТекущиеДанные)» и как её исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке на платформе 1С:Предприятие 8.3 (управляемые формы) программисты часто сталкиваются с ситуацией, когда код, написанный для обработки событий в табличной части, вызывает исключение: Поле объекта не обнаружено (ТекущиеДанные). Чаще всего это происходит в обработчике ПриИзменении конкретной колонки. Давайте подробно разберем причины этой ошибки, проанализируем механику работы управляемого интерфейса и рассмотрим несколько способов корректного написания кода.

Разбор программной ситуации

Рассмотрим пример кода, который привел к ошибке:


&НаКлиенте
Процедура ТоварыНаименованиеПриИзменении(Элемент)
    СтрокаТабличнойЧасти = Элементы.ТоварыНаименование.ТекущиеДанные;
    СтрокаТабличнойЧасти.Цена = РаботаСоСправочниками.РозничнаяЦена(Объект.Дата, СтрокаТабличнойЧасти.Наименование);
    РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти)
КонецПроцедуры

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

Анализ иерархии элементов управляемой формы

Для того чтобы эффективно работать с интерфейсом 1С, проанализируем структуру объектов, с которыми мы взаимодействуем на клиенте:

  1. Таблица формы (например, Элементы.Товары) — это визуальный контейнер, который отображает всю коллекцию строк. Именно этот объект «знает», какая строка в данный момент выделена пользователем. Поэтому свойство ТекущиеДанные доступно именно здесь.
  2. Поле формы (например, Элементы.ТоварыНаименование) — это элемент внутри таблицы, отвечающий за отображение конкретного реквизита в строке. У него нет понятия «текущая строка», так как он сам является частью этой строки.

В сообщении №4 обсуждения на форуме прозвучала мысль, что «реквизит объекта на клиенте не живет». Важно понимать, что это утверждение ошибочно. Данные формы (коллекции строк) прекрасно чувствуют себя на клиенте, но обращаться к ним нужно через правильные интерфейсные механизмы.

Решение №1: Прямое обращение к таблице

Самый простой и очевидный способ исправить ошибку — это обратиться к коллекции Элементы, указав имя самой таблицы, а не её колонки. Рассмотрим исправленный вариант кода:


&НаКлиенте
Процедура ТоварыНаименованиеПриИзменении(Элемент)
    // Обращаемся к таблице "Товары", а не к полю "ТоварыНаименование"
    СтрокаТабличнойЧасти = Элементы.Товары.ТекущиеДанные;
    
    Если СтрокаТабличнойЧасти <> Неопределено Тогда
        СтрокаТабличнойЧасти.Цена = РаботаСоСправочниками.РозничнаяЦена(Объект.Дата, СтрокаТабличнойЧасти.Наименование);
        РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти);
    КонецЕсли;
КонецПроцедуры

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

Решение №2: Использование параметра «Элемент» и свойства «Родитель»

Рассмотрим более универсальный подход. В обработчик события всегда передается параметр Элемент. Этот параметр представляет собой то самое поле, в котором произошло изменение. Поскольку поле находится внутри таблицы, таблица является его родителем.

Выясним преимущества этого метода: вам не нужно жестко прописывать имя таблицы в коде. Если вы переименуете таблицу в дизайнере формы, этот код продолжит работать.


&НаКлиенте
Процедура ТоварыНаименованиеПриИзменении(Элемент)
    // Элемент — это колонка, Элемент.Родитель — это сама таблица
    СтрокаТабличнойЧасти = Элемент.Родитель.ТекущиеДанные;
    
    Если СтрокаТабличнойЧасти <> Неопределено Тогда
        // Выполняем расчеты
        ЦенаТовара = РаботаСоСправочниками.РозничнаяЦена(Объект.Дата, СтрокаТабличнойЧасти.Наименование);
        СтрокаТабличнойЧасти.Цена = ЦенаТовара;
        
        // Вызываем процедуру пересчета суммы
        РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти);
    КонецЕсли;
КонецПроцедуры

Особенности передачи данных на сервер

В приведенных примерах используются серверные функции, такие как РаботаСоСправочниками.РозничнаяЦена. Проанализируем, что происходит при передаче туда переменной СтрокаТабличнойЧасти.

Объект, возвращаемый свойством ТекущиеДанные, имеет тип ДанныеФормыСтруктура. Это легковесный объект, который можно передавать между клиентом и сервером. Однако стоит помнить:

Практические советы по отладке

Если вы столкнулись с подобной ошибкой в другом контексте, выполните следующие шаги для диагностики:

  1. Установите точку останова на строке, где возникает ошибка.
  2. В режиме отладки воспользуйтесь окном «Вычислить выражение» (Shift+F9).
  3. Проверьте тип объекта Элементы.ИмяВашегоЭлемента. Если тип — ПолеФормы, значит, вы пытаетесь получить данные не у того объекта.
  4. Посмотрите список доступных свойств через «Табло», чтобы убедиться, у какого именно объекта в иерархии есть свойство ТекущиеДанные.

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

← На главную