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

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

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

Начинающие разработчики часто сталкиваются со следующей ошибкой при попытке получить текущую строку табличной части:

«Поле объекта не обнаружено (ТекущиеДанные)»

В этой статье мы подробно разберем, почему возникает данная ошибка, как правильно адресовать элементы управляемой формы, а также рассмотрим наиболее эффективные и быстрые способы получения данных из базы данных на сервере.

Выясняем причину ошибки: разница между Таблицей и Полем формы

Давайте проанализируем ситуацию. Ошибка Поле объекта не обнаружено (ТекущиеДанные) возникает в строке кода:

СтрокаТабличнойЧасти = Элементы.ЗапЗапчасть.ТекущиеДанные;

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

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

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

Решение 1. Правильное обращение к таблице формы

Для устранения ошибки нам необходимо обратиться непосредственно к элементу-таблице. Если таблица формы называется Зап, то код получения строки на клиенте должен выглядеть следующим образом:

СтрокаТабличнойЧасти = Элементы.Зап.ТекущиеДанные;

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


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

Примечание: Обращение через Элемент.Родитель отлично работает, если колонки таблицы не объединены в дополнительные визуальные группы. Если группы колонок используются, надежнее обращаться напрямую к имени таблицы через коллекцию Элементы.

Решение 2. Оптимальное получение реквизита на сервере (Без контекста)

После того как мы успешно получили доступ к строке табличной части на клиенте, нам нужно извлечь дополнительный реквизит (например, Обозначение) из выбранной ссылки Запчасть. На клиенте получить реквизиты ссылки напрямую нельзя — для этого требуется обращение к серверу.

Существует два основных подхода к реализации этой задачи на сервере. Рассмотрим их подробнее.

Вариант А. Обращение через точку (Рекомендуемый и самый быстрый способ)

Если нам нужно получить одно или два простых свойства объекта (строку, число, булево), самым оптимальным решением будет создание внеконтекстной функции на сервере с директивой компиляции &НаСервереБезКонтекста. В этом случае сервер не тратит ресурсы на передачу всей формы (контекста) туда и обратно, что значительно экономит сетевой трафик и ускоряет работу интерфейса.

Разберем готовый шаблон реализации:


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

&НаСервереБезКонтекста
Функция ПолучитьОбозначениеНаСервере(СсылкаНаЗапчасть)
    // Обращение через точку на сервере без контекста происходит быстро,
    // так как платформа оптимизирует такие запросы и использует кэш объектов.
    Возврат СсылкаНаЗапчасть.Обозначение;
КонецФункции

Вариант Б. Использование запроса (Новый Запрос)

Использование явных SQL-подобных запросов к базе данных оправдано в тех случаях, когда структура метаданных сложная, либо когда мы получаем информацию не из самого справочника, а из связанных регистров сведений (например, цену запчасти на определенную дату из регистра сведений "ЦеныНоменклатуры").

Посмотрим на пример реализации логики автозаполнения через механизм запросов:


&НаКлиенте
Процедура ЗапЗапчастьПриИзменении(Элемент)
    
    СтрокаТабличнойЧасти = Элементы.Зап.ТекущиеДанные;
    
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ЗначениеЗаполнено(СтрокаТабличнойЧасти.Запчасть) Тогда
        СтрокаТабличнойЧасти.Обозначение = ПолучитьОбозначениеЗапросом(СтрокаТабличнойЧасти.Запчасть);
    Иначе
        СтрокаТабличнойЧасти.Обозначение = "";
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьОбозначениеЗапросом(СсылкаНаЗапчасть)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Запчасти.Обозначение КАК Обозначение
        |ИЗ
        |	Справочник.Запчасти КАК Запчасти
        |ГДЕ
        |	Запчасти.Ссылка = &СсылкаНаЗапчасть";
    
    Запрос.УстановитьПараметр("СсылкаНаЗапчасть", СсылкаНаЗапчасть);
    
    РезультатВыбора = Запрос.Выполнить();
    
    Если Не РезультатВыбора.Пустой() Тогда
        Выборка = РезультатВыбора.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Обозначение;
    КонецЕсли;
    
    Возврат "";
    
КонецФункции

Важные правила разработки при работе с реквизитами ТЧ

Для того чтобы ваш код всегда работал стабильно и не вызывал нареканий при проверке (code review), придерживайтесь следующих правил:

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

← На главную