Как исправить ошибку «Поле объекта не обнаружено (ТипЗначения)» и правильно работать с типами в 1С?

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

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

Выясняем причину ошибки: почему свойство «ТипЗначения» не обнаружено?

Давайте проанализируем строку кода, которая вызвала ошибку у автора темы:


Элемент.ТекущиеДанные.НарушенноеТребование.ТипЗначения = Новый ОписаниеТипов("СправочникСсылка.ТребованияНТД");

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

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

Типичные ошибки при сравнении типов данных в 1С

В ходе обсуждения автор темы попытался решить проблему обходным путем и написал следующее сравнение:


Если ТипЗнч(Элемент.ТекущиеДанные.НарушенноеТребование) <> Новый ОписаниеТипов("СправочникСсылка.ТребованияНТД") Тогда
    // Какое-то действие
КонецЕсли;

Разберем по шагам, почему это условие всегда будет срабатывать как «Не равно» (Истина), даже если в ячейке фактически находится нужный справочник. Дело в том, что здесь сравниваются объекты совершенно разных типов:

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


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

Если же перед нами стоит задача проверить, входит ли тип значения в составной тип (описание типов), мы должны использовать специальный метод:


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

Решение 1: Программное приведение значения к нужному типу

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

Рассмотрим безопасный вариант реализации с обязательной проверкой на то, что строка таблицы вообще выбрана:


ТекДанные = Элемент.ТекущиеДанные;
Если ТекДанные <> Неопределено Тогда
    // Присваиваем пустую ссылку нужного типа напрямую
    ТекДанные.НарушенноеТребование = Справочники.ТребованияНТД.ПустаяСсылка();
КонецЕсли;

Если тип данных определяется динамически на основе метаданных или внешних условий, мы можем воспользоваться методом ПривестиЗначение() объекта ОписаниеТипов. Этот метод преобразует переданное значение к наиболее подходящему типу из описания:


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

Решение 2: Ограничение типа на уровне интерфейса (в событии ПриНачалеВыбора)

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

Рассмотрим, как правильно настроить это поведение. Для поля ввода в табличной части нам необходимо определить клиентский обработчик события ПриНачалеВыбора:


&НаКлиенте
Процедура ТаблицаТребованийНарушенноеТребованиеПриНачалеВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // В данном контексте переменная "Элемент" — это ПолеФормы (интерфейсный элемент управления)
    // Устанавливаем ограничение типов для интерактивного выбора
    Элемент.ОграничениеТипа = Новый ОписаниеТипов("СправочникСсылка.ТребованияНТД");
    
    // Отключаем обязательный диалог выбора типа, если реквизит составной
    Элемент.ВыбиратьТип = Ложь;
    
КонецПроцедуры

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

Резюме и лучшие практики работы с типами

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

← На главную