При разработке на платформе 1С:Предприятие 8.3 (управляемые формы) программисты часто сталкиваются с ситуацией, когда код, написанный для обработки событий в табличной части, вызывает исключение: Поле объекта не обнаружено (ТекущиеДанные). Чаще всего это происходит в обработчике ПриИзменении конкретной колонки. Давайте подробно разберем причины этой ошибки, проанализируем механику работы управляемого интерфейса и рассмотрим несколько способов корректного написания кода.
Рассмотрим пример кода, который привел к ошибке:
&НаКлиенте
Процедура ТоварыНаименованиеПриИзменении(Элемент)
СтрокаТабличнойЧасти = Элементы.ТоварыНаименование.ТекущиеДанные;
СтрокаТабличнойЧасти.Цена = РаботаСоСправочниками.РозничнаяЦена(Объект.Дата, СтрокаТабличнойЧасти.Наименование);
РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти)
КонецПроцедуры
В данном фрагменте разработчик пытается программно вычислить цену товара при выборе его наименования. Ошибка возникает в первой же строке после объявления процедуры. Проблема заключается в объекте Элементы.ТоварыНаименование. Выясним причину: в иерархии элементов формы ТоварыНаименование — это Поле формы (конкретная колонка), в то время как свойство ТекущиеДанные реализовано только для элемента типа Таблица формы.
Для того чтобы эффективно работать с интерфейсом 1С, проанализируем структуру объектов, с которыми мы взаимодействуем на клиенте:
Элементы.Товары) — это визуальный контейнер, который отображает всю коллекцию строк. Именно этот объект «знает», какая строка в данный момент выделена пользователем. Поэтому свойство ТекущиеДанные доступно именно здесь.Элементы.ТоварыНаименование) — это элемент внутри таблицы, отвечающий за отображение конкретного реквизита в строке. У него нет понятия «текущая строка», так как он сам является частью этой строки.В сообщении №4 обсуждения на форуме прозвучала мысль, что «реквизит объекта на клиенте не живет». Важно понимать, что это утверждение ошибочно. Данные формы (коллекции строк) прекрасно чувствуют себя на клиенте, но обращаться к ним нужно через правильные интерфейсные механизмы.
Самый простой и очевидный способ исправить ошибку — это обратиться к коллекции Элементы, указав имя самой таблицы, а не её колонки. Рассмотрим исправленный вариант кода:
&НаКлиенте
Процедура ТоварыНаименованиеПриИзменении(Элемент)
// Обращаемся к таблице "Товары", а не к полю "ТоварыНаименование"
СтрокаТабличнойЧасти = Элементы.Товары.ТекущиеДанные;
Если СтрокаТабличнойЧасти <> Неопределено Тогда
СтрокаТабличнойЧасти.Цена = РаботаСоСправочниками.РозничнаяЦена(Объект.Дата, СтрокаТабличнойЧасти.Наименование);
РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти);
КонецЕсли;
КонецПроцедуры
Важный нюанс: Мы добавили проверку на Неопределено. Это критически важно, так как в некоторых случаях (например, при программном изменении данных или если строка была удалена в момент обработки) ТекущиеДанные могут быть не заполнены. Обращение к свойствам Неопределено вызовет новую ошибку.
Рассмотрим более универсальный подход. В обработчик события всегда передается параметр Элемент. Этот параметр представляет собой то самое поле, в котором произошло изменение. Поскольку поле находится внутри таблицы, таблица является его родителем.
Выясним преимущества этого метода: вам не нужно жестко прописывать имя таблицы в коде. Если вы переименуете таблицу в дизайнере формы, этот код продолжит работать.
&НаКлиенте
Процедура ТоварыНаименованиеПриИзменении(Элемент)
// Элемент — это колонка, Элемент.Родитель — это сама таблица
СтрокаТабличнойЧасти = Элемент.Родитель.ТекущиеДанные;
Если СтрокаТабличнойЧасти <> Неопределено Тогда
// Выполняем расчеты
ЦенаТовара = РаботаСоСправочниками.РозничнаяЦена(Объект.Дата, СтрокаТабличнойЧасти.Наименование);
СтрокаТабличнойЧасти.Цена = ЦенаТовара;
// Вызываем процедуру пересчета суммы
РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти);
КонецЕсли;
КонецПроцедуры
В приведенных примерах используются серверные функции, такие как РаботаСоСправочниками.РозничнаяЦена. Проанализируем, что происходит при передаче туда переменной СтрокаТабличнойЧасти.
Объект, возвращаемый свойством ТекущиеДанные, имеет тип ДанныеФормыСтруктура. Это легковесный объект, который можно передавать между клиентом и сервером. Однако стоит помнить:
Записать()) внутри серверной функции, работая с ДанныеФормыСтруктура, так как это не объект базы данных, а лишь данные интерфейса.Если вы столкнулись с подобной ошибкой в другом контексте, выполните следующие шаги для диагностики:
Элементы.ИмяВашегоЭлемента. Если тип — ПолеФормы, значит, вы пытаетесь получить данные не у того объекта.ТекущиеДанные.Таким образом, для исправления ошибки достаточно помнить простое правило: свойство ТекущиеДанные принадлежит таблице, а не её колонкам. Используйте либо прямое обращение к таблице по имени, либо обращение через Элемент.Родитель для написания более гибкого и отказоустойчивого кода.