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

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

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

Разбор причины: почему «Номер» — это только следствие

Рассмотрим природу ошибки. Сообщение «Значение не является значением объектного типа (ИмяРеквизита)» означает, что программа пытается обратиться к реквизиту (в нашем случае Номер) переменной, которая сама по себе не является объектом. В контексте 1С это означает, что в переменной находится не ссылка на документ, а Неопределено, NULL или ПустаяСсылка.

Многие начинающие разработчики ошибочно полагают, что если в номере документа появилась буква «О» или любой другой символ, 1С не может его прочитать. Это заблуждение. Тип данных Номер в документах 1С — это Строка. Строка может содержать любые символы. Проблема кроется глубже: алгоритм просто «теряет» объект по пути к выводу на печать.

Шаг 1. Анализ кода и поиск уязвимого места

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


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

В этом примере мы видим прямое обращение через точку: ВыборкаСтрок.Документ.Номер. Если в поле Документ окажется пустое значение, система не сможет найти у него свойство Номер и выдаст критическую ошибку. Выясним причину, почему объект может быть пустым.

Шаг 2. Почему в выборку попадает пустое значение?

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

  1. Несоответствие типов в реквизите: Если реквизит имеет составной тип, убедитесь, что в списке разрешенных типов отмечен документ «Корректировка реализации». Если галочка не стоит, при попытке записать ссылку в базу она превратится в Неопределено.
  2. Ошибки в запросе: Если используется ЛЕВОЕ СОЕДИНЕНИЕ, и для какой-то строки не найдено соответствие, в поле документа попадет NULL.
  3. Неполная логика условий: Если код обрабатывает только конкретные типы (например, только РеализацияТоваровУслуг), а в таблицу попал другой документ, переменные могут остаться неинициализированными.

Шаг 3. Внедрение защитного кода (Метод 1: Проверка на заполненность)

Самый простой и эффективный способ избежать падения системы — добавить проверку ЗначениеЗаполнено() перед обращением к свойствам объекта. Перепишем наш цикл в более безопасном виде:


Пока ВыборкаСтрок.Следующий() Цикл
    // Проверяем, что документ вообще существует
    Если НЕ ЗначениеЗаполнено(ВыборкаСтрок.Документ) Тогда
        Продолжить; // Пропускаем пустую строку
    КонецЕсли;

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

Шаг 4. Использование функций общего назначения (Метод 2)

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

Рассмотрим пример использования:


// Вместо прямого обращения:
// Номер = ВыборкаСтрок.Документ.Номер; 

// Используем безопасный метод:
Номер = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВыборкаСтрок.Документ, "Номер");

Если Номер = Неопределено Тогда
    Номер = "б/н";
КонецЕсли;

Шаг 5. Отладка и поиск «невидимых» ошибок

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

  1. Установите точку останова в начале цикла Пока ВыборкаСтрок.Следующий().
  2. В меню отладчика выберите «Останавливаться по ошибке».
  3. Запустите печать. Когда система остановится, откройте окно «Вычислить выражение».
  4. Проверьте значение ВыборкаСтрок.Документ. Если там NULL или {"#", ...} (битая ссылка), значит проблема в данных или запросе.

Часто выясняется, что в табличной части документа просто существует лишняя пустая строка, которую пользователь не заметил. В этом случае достаточно добавить программный пропуск пустых строк, как показано в Шаге 3.

Рекомендации по работе с номерами документов

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

  1. Префиксы: Функция ПрефиксацияОбъектовКлиентСервер.НомерНаПечать специально создана для того, чтобы отсекать префиксы организации и информационных баз. Буква «О» в начале номера часто является частью префикса.
  2. Длина номера: Если номер был отредактирован вручную и стал длиннее положенного, функция может вернуть пустую строку, но никогда не вызовет ошибку «Значение не является значением объектного типа».
  3. Тип номера: Всегда помните, что Номер — это строка. Не пытайтесь преобразовывать его к числу явным образом, если в базе разрешена ручная нумерация.

Подведем итог: Ошибка «не является значением объектного типа (Номер)» всегда свидетельствует о попытке «достучаться» до данных пустого объекта. Решением является либо очистка данных (удаление пустых строк в документе), либо добавление в код проверки ЗначениеЗаполнено(), либо использование безопасных методов получения реквизитов из Библиотеки Стандартных Подсистем.

← На главную