При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с крайне неинформативной ошибкой: "Значение не является значением объектного типа". Особенно странно она выглядит в ситуациях, когда код кажется абсолютно корректным, например, при попытке получить ссылку для нового документа. В данной статье мы подробно разберем, почему возникает эта ошибка при обращении к коллекции Документы, и как ее эффективно устранить.
Рассмотрим ситуацию, описанную пользователем: в процедуре ПередЗаписью модуля документа (в данном случае — Накладная в конфигурации УНФ) выполняется стандартный код для генерации ссылки нового объекта. Код выглядит следующим образом:
СсылкаНового = Документы.Накладная.ПолучитьСсылку();
Несмотря на то, что синтаксическая проверка не выявляет ошибок, в режиме "1С:Предприятие" система выбрасывает исключение. Проанализируем, что именно происходит. Ошибка "Значение не является значением объектного типа" означает, что программа пытается обратиться к методу или свойству (в нашем случае — к свойству Накладная или методу ПолучитьСсылку) у переменной, которая не является объектом или менеджером. То есть, с точки зрения платформы, слово Документы в этот момент не является глобальной коллекцией менеджеров документов.
Это самая распространенная причина. В языке 1С существует иерархия контекстов. Если в модуле объекта, в процедуре или функции объявлена переменная, реквизит или параметр с именем Документы, то платформа "забывает" про глобальную коллекцию и начинает обращаться к этой локальной переменной. Выясним, как это проверить.
Проанализируем ситуацию: если выше по коду или в заголовке процедуры случайно появилось объявление, подобное этому:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Где-то в коде случайно определена переменная
Документы = "Список документов";
// Теперь Документы — это строка, а не коллекция менеджеров
СсылкаНового = Документы.Накладная.ПолучитьСсылку(); // ОШИБКА!
КонецПроцедуры
Для диагностики мы можем использовать отладчик или простую команду Сообщить, чтобы узнать, чем на самом деле является Документы в проблемной строке:
Сообщить(ТипЗнч(Документы));
Если тип значения отличается от КоллекцияМенеджеровДокументов, значит, имя перекрыто локальной логикой. Рассмотрим решение: необходимо найти и переименовать локальную переменную или параметр, конфликтующий с глобальным именем.
Как показывает практика практикующих разработчиков, если переименование локальных переменных не помогает или их просто нет, эффективным решением становится перенос кода в общий модуль. Рассмотрим, почему это работает.
В общем модуле (особенно если установлены свойства "Сервер" и "Вызов сервера") контекст является "чистым". Там нет реквизитов формы или объекта, которые могли бы неявно конфликтовать с системными именами. Разберем по шагам, как реализовать этот метод:
РаботаСДокументамиСервер) или используем существующий.
Функция ПолучитьСсылкуДляНовойНакладной() Экспорт
Возврат Документы.ПриходнаяНакладная.ПолучитьСсылку();
КонецФункции
Затем в модуле самого документа вызовем эту функцию:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() Тогда
СсылкаНового = РаботаСДокументамиСервер.ПолучитьСсылкуДляНовойНакладной();
УстановитьСсылкуНового(СсылкаНового);
КонецЕсли;
КонецПроцедуры
Такой подход гарантирует, что обращение к Документы будет идти напрямую к метаданным платформы без помех со стороны контекста конкретного объекта.
Проанализируем еще один нюанс. В типовых конфигурациях, таких как УНФ, документы часто имеют названия, отличные от привычных "разговорных". Например, документа с именем Накладная в метаданных может просто не существовать. Вместо него могут быть ПриходнаяНакладная или РасходнаяНакладная.
Если вы пишете Документы.Накладная, и объекта с именем Накладная нет в конфигураторе, то свойство Накладная вернет Неопределено. Следовательно, попытка вызвать метод .ПолучитьСсылку() у Неопределено приведет к искомой ошибке.
Рекомендация: всегда проверяйте точное имя объекта в дереве метаданных конфигуратора и используйте контекстную подсказку (Ctrl + Space).
Иногда проблема кроется не в коде, а в некорректном состоянии локального кэша платформы. Если тестирование и исправление (T&R), а также утилита checkDBFL не находят ошибок, попробуйте выполнить следующие действия:
Мы рассмотрели несколько сценариев возникновения ошибки "Значение не является значением объектного типа" при работе с документами. Подведем итог: чаще всего проблема вызвана конфликтом имен в модуле объекта или обращением к несуществующему имени метаданных. Перенос кода в общий модуль — это наиболее надежный архитектурный способ решения, который изолирует выполнение кода от специфического контекста документа и делает систему более стабильной.