Как исправить ошибку «Значение не является значением объектного типа (ДокументыОснования)» при получении данных в 1С

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

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

Выясняем причину возникновения ошибки

Ошибка Значение не является значением объектного типа буквально означает, что система попыталась обратиться «через точку» к переменной, которая не является ссылкой на документ, структурой или другим сложным объектом. В контексте кода ДанныеСсылкиДокументов.Ссылка.ДокументыОснования проблема может крыться в одном из трех звеньев:

  1. Переменная ДанныеСсылкиДокументов сама по себе не является тем, чем кажется (например, это Неопределено или пустая строка).
  2. Свойство Ссылка у этой переменной пустое или имеет тип, отличный от ссылочного.
  3. У конкретного типа документа, ссылка на который хранится в поле Ссылка, в метаданных просто отсутствует табличная часть ДокументыОснования.

Проанализируем ситуацию: если ваш код успешно работал для одного типа документов, но «упал» на другом, значит, в систему попал объект иной структуры. Например, у документа «Реализация товаров и услуг» такая табличная часть есть, а у «Заказа клиента» или «Перемещения» её может не быть, либо она называется иначе.

Шаг 1: Использование отладчика для проверки типов

Первым делом нам необходимо включить отладчик и установить точку останова на строке, где возникает ошибка. Рассмотрим, что именно нужно проверить в окне «Вычислить выражение» (Shift+F9):

Если в процессе отладки выяснится, что ДанныеСсылкиДокументов.Ссылка возвращает Неопределено или Null, то любая попытка обратиться к .ДокументыОснования вызовет фатальную ошибку. Это часто случается, если данные выбираются запросом с ЛЕВЫМ СОЕДИНЕНИЕМ, и соответствие в базе не было найдено.

Шаг 2: Проверка наличия реквизита в метаданных

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


// Проверяем, что ссылка существует и это действительно ссылка на документ
Если ЗначениеЗаполнено(ДанныеСсылкиДокументов.Ссылка) Тогда
    МетаданныеОбъекта = ДанныеСсылкиДокументов.Ссылка.Метаданные();
    
    // Проверяем наличие табличной части "ДокументыОснования" в метаданных
    Если МетаданныеОбъекта.ТабличныеЧасти.Найти("ДокументыОснования") <> Неопределено Тогда
        Для каждого СтрокаОснование Из ДанныеСсылкиДокументов.Ссылка.ДокументыОснования Цикл
            НомерРеализации = СтрокаОснование.ДокументОснование.Номер;
        КонецЦикла;
    Иначе
        // Обработка случая, когда такой таблицы нет у данного типа документа
        ЗаписьЖурналаРегистрации("Печать", УровеньЖурналаРегистрации.Предупреждение, , , 
            "У документа " + ДанныеСсылкиДокументов.Ссылка + " отсутствует ТЧ ДокументыОснования");
    КонецЕсли;
КонецЕсли;

Шаг 3: Оптимизация получения данных через «ОбщегоНазначения»

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


// Используем функцию БСП для получения таблицы
ТаблицаОснований = ОбщегоНазначения.ВыгрузитьТабличнуюЧасть(ДанныеСсылкиДокументов.Ссылка, "ДокументыОснования");

Для каждого СтрокаОснование Из ТаблицаОснований Цикл
    // Работаем с данными
    ДокументОснование = СтрокаОснование.ДокументОснование;
    // ...
КонецЦикла;

Преимущество метода ОбщегоНазначения.ВыгрузитьТабличнуюЧасть заключается в том, что он отработает корректно даже в сложных случаях, а ваш код станет более читаемым и стабильным.

Проблема «нейминга» и читаемости кода

Проанализируем пример из обсуждения: использование имен переменных типа строка и строка1 крайне не рекомендуется. Это затрудняет отладку и понимание логики. Рекомендуем давать переменным осмысленные имена: ТекущееОснование, СтрокаТовара и так далее. Это поможет вам быстрее ориентироваться в коде, когда вы вернетесь к нему спустя время.

Рекомендации по исправлению в контексте Транспортной накладной

Поскольку вы работаете в модуле менеджера обработки ПечатьТранспортнойНакладной, важно учитывать, что структура данных может зависеть от версии конфигурации. Если вы пытаетесь достать номер реализации:

  1. Убедитесь, что ДанныеСсылкиДокументов — это не массив. Если это массив или коллекция строк, к ней нельзя обращаться напрямую, сначала нужно получить конкретный элемент (например, ДанныеСсылкиДокументов[0]).
  2. Если основанием является не один документ, а несколько, логика с простым присваиванием НомерРеализации = ... в цикле некорректна, так как в переменной останется номер только последнего документа. Лучше собирать номера в строку или массив.

Разберем пример сбора всех номеров оснований в одну строку:


СписокНомеров = Новый СписокЗначений;
Если ДанныеСсылкиДокументов.Ссылка.Метаданные().ТабличныеЧасти.Найти("ДокументыОснования") <> Неопределено Тогда
    Для каждого ТекСтрока Из ДанныеСсылкиДокументов.Ссылка.ДокументыОснования Цикл
        Если ЗначениеЗаполнено(ТекСтрока.ДокументОснование) Тогда
            СписокНомеров.Добавить(ТекСтрока.ДокументОснование.Номер);
        КонецЕсли;
    КонецЦикла;
КонецЕсли;
ВсеНомера = СписокНомеров.ВыгрузитьЗначения();
СтрокаНомеров = СтрСоединить(ВсеНомера, ", ");

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

← На главную