При работе с расширениями в 1С:Предприятии программисты часто сталкиваются с задачами, требующими глубокого понимания механики платформы. Одной из таких распространенных ситуаций является попытка создания или модификации объектов конфигурации через расширение, которая может приводить к ошибкам типа данных. В данном случае, мы рассмотрим проблему, когда при перехвате команды формы документа и попытке создания нового элемента справочника в расширении возникает ошибка "Значение не является значением объектного типа (Кому)".
Автор исходного сообщения столкнулся именно с такой ситуацией. Он перехватывает команду формы документа и в ее обработчике вызывает серверную процедуру для создания элемента справочника ВажныеСообщения. При этом, код успешно работает при вызове из отдельной обработки, но выдает ошибку при вызове из документа в расширении. Давайте подробнее разберем этот сценарий и выясним возможные причины возникновения ошибки, а также способы ее устранения.
Рассмотрим код, который вызывает ошибку:
&НаСервере
Процедура СообщениеЭД()
НовоеСообщение = Справочники.ВажныеСообщения.СоздатьЭлемент();
НовоеСообщение.Кому = ПолучитьЭД();
НовоеСообщение.Текст = "Счет согласован ОС";
//НовоеСообщение.НавигационнаяСсылка = ПолучитьНавигационнуюСсылку(Объект.Ссылка);
НовоеСообщение.Пояснение = "По счету...";
НовоеСообщение.ОтКого = ПолучитьОС();
НовоеСообщение.Записать();
КонецПроцедуры
Ошибка "Значение не является значением объектного типа (Кому)" возникает на строке НовоеСообщение.Кому = ПолучитьЭД();. Это явно указывает на то, что значение, которое возвращает функция ПолучитьЭД(), не является тем типом данных, который ожидает реквизит Кому справочника ВажныеСообщения. Или же сам реквизит Кому не был корректно инициализирован или доступен.
Одна из самых частых причин подобных ошибок в расширениях — это некорректное заимствование объектов или их реквизитов. Даже если мы думаем, что все заимствовано, стоит еще раз внимательно проверить.
ВажныеСообщения полностью заимствован в расширение. Это базовая необходимость для работы с его элементами.Кому не является стандартным реквизитом, а был добавлен в конфигурации или является заимствованным из другой конфигурации в основную, то его также необходимо явно заимствовать в расширение. Даже если справочник заимствован, его реквизиты, особенно нетиповые, могут требовать отдельного заимствования для корректного доступа.Кому в конфигурации. Вероятнее всего, это ссылочный тип (например, ссылка на другой справочник, такой как Пользователи, Контрагенты или другой объект СправочникСсылка.<ИмяСправочника>). Значение, которое присваивается этому реквизиту, должно быть совместимого ссылочного типа или ссылкой на существующий объект. Если реквизит имеет составной тип данных, убедитесь, что присваиваемое значение соответствует одному из допустимых типов.Автор утверждает, что все заимствовано. Однако, проблема может быть не в самом факте заимствования, а в контексте, в котором происходит обращение к заимствованным данным.
Хотя процедура СообщениеЭД помечена директивой &НаСервере, что означает ее выполнение на сервере, проблема может крыться в том, как эта серверная процедура вызывается, или в том, что функции, используемые внутри нее (ПолучитьЭД(), ПолучитьОС()), ведут себя по-разному в разных контекстах.
СообщениеЭД() также корректно обрабатывают серверный/клиентский контекст.ПолучитьЭД()? Это критически важный момент. Ошибка "Значение не является значением объектного типа" прямо указывает на то, что результат функции ПолучитьЭД() не является ссылочным типом, или является пустой ссылкой, или вообще Неопределено, когда ожидается объект.
ПолучитьЭД() использует метод НайтиПоНаименованию() (как упомянул автор для тестирования), то в случае, если элемент с таким наименованием не найден, метод вернет пустую ссылку. Попытка присвоить пустую ссылку реквизиту, который не допускает пустых значений (что редко, но возможно при определенных ограничениях), или последующие попытки обращения к свойствам этой "пустой" ссылки могут вызвать подобную ошибку. В данном случае, ошибка происходит непосредственно при присвоении, что чаще указывает на несоответствие типа.ПолучитьЭД() в контексте расширения возвращает не ссылку, а, например, строку или число, в то время как реквизит Кому ожидает ссылку на справочник или другой объект.ПолучитьЭД(), которые приводят к возврату некорректного значения или Неопределено.Даже если код синтаксически верен и объекты заимствованы, недостаток прав доступа у пользователя, от имени которого выполняется код, может привести к непредсказуемому поведению, включая ошибки типа данных при попытке записи в реквизиты.
ВажныеСообщения.Кому справочника ВажныеСообщения. Если реквизит имеет ограничения по доступу (например, RLS), это может быть причиной.Кому имеет составной тип данных, убедитесь, что у пользователя есть права на работу со всеми типами, которые входят в этот составной тип, и на запись именно того типа, который вы пытаетесь присвоить.Наиболее эффективным способом выявления точной причины ошибки является пошаговое выполнение кода в отладчике.
НовоеСообщение.Кому = ПолучитьЭД();.НовоеСообщение. Убедитесь, что это действительно элемент справочника ВажныеСообщения (СправочникОбъект.ВажныеСообщения).ПолучитьЭД() отдельно (например, добавив временную переменную ЗначениеЭД = ПолучитьЭД(); перед проблемной строкой) и посмотрите, что именно возвращает эта функция: ее тип и значение.Кому. Если ПолучитьЭД() возвращает Неопределено, пустую ссылку или тип, несовместимый с типом реквизита Кому, вы увидите это в отладчике.ПолучитьЭД() и ПолучитьОС(). Убедитесь, что они всегда возвращают корректные ссылочные объекты, а не Неопределено или другие типы данных, которые могут быть несовместимы с реквизитами.Иногда, особенно после активных изменений в расширениях, проблемы могут быть связаны с устаревшим кэшем метаданных или неактуальной версией платформы.
%LOCALAPPDATA%\1C\1CE\ и %APPDATA%\1C\1CE\) и перезапустив базу. Это может помочь, если система использует устаревшие метаданные для расширения.Раз мы уже выяснили, что код в отдельной обработке работает, это означает, что сама логика получения значений и создания элемента, скорее всего, верна. Это сужает круг поиска проблемы до контекста выполнения или специфики работы расширений с документами.
ПолучитьЭД() присвойте реквизиту Кому явно заданную ссылку на существующий объект, например: НовоеСообщение.Кому = Справочники.Пользователи.НайтиПоКоду("000000001"); (или другой подходящий справочник). Если после этого код начнет работать, проблема точно в функции ПолучитьЭД().Таким образом, для решения проблемы необходимо методично пройти по всем пунктам диагностики, начиная с проверки типов и значений в отладчике, и заканчивая анализом прав доступа и заимствования объектов. Вероятнее всего, проблема кроется либо в типе значения, возвращаемого функцией ПолучитьЭД() в контексте расширения/документа, либо в недостаточных правах на запись в реквизит Кому, специфичных для расширения.