В практике программирования на платформе 1С:Предприятие одной из самых частых ошибок, с которой сталкиваются разработчики, является сообщение: «Значение не является значением объектного типа». Эта ошибка может возникать при обращении к свойствам справочников, документов или табличным частям. В данном материале мы подробно разберем ситуацию, когда ошибка возникает при попытке обратиться к коллекции ДополнительныеРеквизиты, проанализируем причины и выработаем правильные алгоритмы решения.
Рассмотрим конкретный пример кода, который вызывает ошибку. Представим, что у нас есть функция, цель которой — найти значение дополнительного реквизита «ДоверенностьРуководителяОрганизации» для переданной организации.
Функция ПолучитьДоверенностьРуководителяОрганизации(Организация)
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "ДоверенностьРуководителяОрганизации");
// В этой строке возникает ошибка:
НайденнаяСтрока = Организация.ДополнительныеРеквизиты.НайтиСтроки(Новый Структура("Свойство", Свойство));
Если НайденнаяСтрока.Количество() > 0 Тогда
ДоверенностьРуководителяОрганизации = НайденнаяСтрока[0].Значение;
Иначе
ДоверенностьРуководителяОрганизации = "_";
КонецЕсли;
Возврат ДоверенностьРуководителяОрганизации;
КонецФункции
При выполнении строки с методом НайтиСтроки система аварийно останавливает выполнение и сообщает, что значение переменной Организация не является объектным типом, у которого есть свойство ДополнительныеРеквизиты.
Давайте разберемся, что именно происходит «под капотом» платформы. Когда мы пишем конструкцию вида Переменная.Свойство, платформа ожидает, что в переменной находится объект (или ссылка на него), который имеет структуру данных, включающую это свойство. Если же в переменной находится простой тип (число, строка, булево) или пустое значение (Неопределено, Null), то у такого значения нет никаких «дочерних» свойств. Попытка обратиться к ним через точку и вызывает ошибку.
Первый и самый важный шаг в решении подобной проблемы — понять, что именно находится в переменной Организация в момент падения кода. Мы не должны гадать; нам нужны точные данные.
Выполним следующие действия в режиме конфигуратора:
Организация.ДополнительныеРеквизиты.Организация и нажмем Shift+F9 (вычислить выражение).В окне табло мы увидим текущее значение и, что важнее, тип значения. Возможны следующие варианты, которые приводят к ошибке:
ДополнительныеРеквизиты.Даже если мы исправим ошибку передачи параметра и убедимся, что Организация — это СправочникСсылка, приведенный выше код остается несовершенным. Рассмотрим его недостатки и способы улучшения.
Обратим внимание на строку:
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "ДоверенностьРуководителяОрганизации");
Этот подход крайне ненадежен. Метод ищет свойство по строковому представлению имени (которое задается в конфигураторе). Если разработчик переименует свойство, код перестанет работать. Кроме того, поиск по строке может быть медленным.
Решение: Используйте предопределенные элементы (если они есть) или ссылки. В типовых конфигурациях правильнее использовать механизмы БСП (Библиотеки Стандартных Подсистем), о чем мы поговорим ниже.
Конструкция Организация.ДополнительныеРеквизиты при обращении к ссылке вызывает неявное чтение всего объекта из базы данных на сервер приложения. Платформа «поднимает» в память весь объект целиком только ради того, чтобы вы могли прочитать одну табличную часть. Если этот код выполняется в цикле обработки документов, производительность системы может существенно снизиться.
Решение: Для получения значений реквизитов (в том числе дополнительных) следует использовать запросы. Запрос выберет только нужные поля, не нагружая память лишними данными.
Пример правильного получения значения через запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОрганизацииДополнительныеРеквизиты.Значение КАК Значение
|ИЗ
| Справочник.Организации.ДополнительныеРеквизиты КАК ОрганизацииДополнительныеРеквизиты
|ГДЕ
| ОрганизацииДополнительныеРеквизиты.Ссылка = &Ссылка
| И ОрганизацииДополнительныеРеквизиты.Свойство.Имя = &ИмяСвойства";
Запрос.УстановитьПараметр("Ссылка", Организация);
Запрос.УстановитьПараметр("ИмяСвойства", "ДоверенностьРуководителяОрганизации");
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Значение;
КонецЕсли;
В современных конфигурациях (ERP, Бухгалтерия Предприятия, Управление Торговлей) изобретать велосипед для чтения доп. реквизитов не нужно. Существует общий модуль УправлениеСвойствами, который берет на себя всю сложную работу, включая кэширование.
Рассмотрим, как получить значение свойства, используя стандарты 1С:
// Получаем ссылку на свойство (ПланВидовХарактеристик)
// Желательно найти его заранее или передать ссылку, а не искать по наименованию каждый раз
СвойствоСсылка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Доверенность руководителя");
// Используем функцию БСП для получения значений
ЗначенияСвойств = УправлениеСвойствами.ПолучитьЗначенияСвойств(Организация);
ЗначениеДоверенности = ЗначенияСвойств.Получить(СвойствоСсылка);
Такой подход делает код более чистым, поддерживаемым и устойчивым к изменениям в платформе.
Еще один важный нюанс — где выполняется ваш код. Табличная часть ДополнительныеРеквизиты физически хранится в базе данных. Доступ к ней через объектную модель (через точку) возможен:
Если вы пытаетесь написать код вида Объект.ДополнительныеРеквизиты в модуле формы НаКлиенте, вы можете столкнуться с тем, что коллекция недоступна или пуста, так как на клиент передается не весь объект, а структура ДанныеФормы. Для работы с дополнительными реквизитами на клиенте обычно используются специальные серверные вызовы или функции БСП, адаптированные для работы с формами.
Подводя итог, для исправления ошибки «Значение не является значением объектного типа» при работе с дополнительными реквизитами, выполните следующие шаги:
ТипЗнч(Организация)), что переменная содержит именно СправочникСсылка.Организации, а не Неопределено или строку.Организация.Пустая(), то выходите из функции до обращения к свойствам.УправлениеСвойствами, если ваша конфигурация построена на БСП.Соблюдение этих правил поможет избежать ошибок времени выполнения и сделает ваш код профессиональным и быстрым.