Почему возникает ошибка "Значение не является значением объектного типа" при создании элемента справочника в расширении 1С из команды формы документа?

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

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

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

Рассмотрим код, который вызывает ошибку:


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

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

1. Проверка заимствования объектов и их реквизитов в расширении

Одна из самых частых причин подобных ошибок в расширениях — это некорректное заимствование объектов или их реквизитов. Даже если мы думаем, что все заимствовано, стоит еще раз внимательно проверить.

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

Автор утверждает, что все заимствовано. Однако, проблема может быть не в самом факте заимствования, а в контексте, в котором происходит обращение к заимствованным данным.

2. Анализ контекста выполнения кода: серверные и клиентские вызовы

Хотя процедура СообщениеЭД помечена директивой &НаСервере, что означает ее выполнение на сервере, проблема может крыться в том, как эта серверная процедура вызывается, или в том, что функции, используемые внутри нее (ПолучитьЭД(), ПолучитьОС()), ведут себя по-разному в разных контекстах.

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

3. Проблемы с правами доступа

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

  1. Права на создание элемента: Убедитесь, что у пользователя есть права на создание элементов справочника ВажныеСообщения.
  2. Права на запись в реквизит "Кому": В расширениях часто требуется явное указание прав доступа к заимствованным объектам и их реквизитам, даже если в основной конфигурации они заданы. Проверьте роли и права пользователя на запись в реквизит Кому справочника ВажныеСообщения. Если реквизит имеет ограничения по доступу (например, RLS), это может быть причиной.
  3. Особенности составных типов: Если реквизит Кому имеет составной тип данных, убедитесь, что у пользователя есть права на работу со всеми типами, которые входят в этот составной тип, и на запись именно того типа, который вы пытаетесь присвоить.

4. Использование отладчика для детальной диагностики

Наиболее эффективным способом выявления точной причины ошибки является пошаговое выполнение кода в отладчике.

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

5. Кэш метаданных и версия платформы

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

  1. Очистка кэша: Попробуйте очистить кэш 1С, удалив папки кэша пользователя (обычно находятся в %LOCALAPPDATA%\1C\1CE\ и %APPDATA%\1C\1CE\) и перезапустив базу. Это может помочь, если система использует устаревшие метаданные для расширения.
  2. Версия платформы: Убедитесь, что используемая версия платформы 1С:Предприятие актуальна и совместима с функционалом расширений. Иногда в старых версиях могут быть известные ошибки, связанные с работой расширений. Обновление платформы до последней стабильной версии может решить проблему.

6. Дополнительные рекомендации по диагностике

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

  1. Сравнение контекстов: Попробуйте максимально точно воспроизвести условия вызова в обработке, которые успешно работают. Какие параметры передаются? От имени какого пользователя запускается? Какие объекты доступны?
  2. Временное упрощение: Для изоляции проблемы попробуйте временно упростить код:
    • Вместо вызова ПолучитьЭД() присвойте реквизиту Кому явно заданную ссылку на существующий объект, например: НовоеСообщение.Кому = Справочники.Пользователи.НайтиПоКоду("000000001"); (или другой подходящий справочник). Если после этого код начнет работать, проблема точно в функции ПолучитьЭД().

Таким образом, для решения проблемы необходимо методично пройти по всем пунктам диагностики, начиная с проверки типов и значений в отладчике, и заканчивая анализом прав доступа и заимствования объектов. Вероятнее всего, проблема кроется либо в типе значения, возвращаемого функцией ПолучитьЭД() в контексте расширения/документа, либо в недостаточных правах на запись в реквизит Кому, специфичных для расширения.

← На главную