Почему при создании документа из журнала с отбором возникает ошибка "Поле объекта не обнаружено (Ссылка)"?

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

При работе в журналах документов или динамических списках разработчики часто сталкиваются с нетипичным поведением: при обычном открытии журнала новый документ создается без проблем, но стоит пользователю установить любой отбор и нажать кнопку "Создать", как система выдает критическую ошибку выполнения обработчика ОбработкаЗаполнения.

Разберем подробнее механику работы платформы «1С:Предприятие», проанализируем причины возникновения этой проблемы и рассмотрим правильные способы её решения в коде модуля объекта.

Причина поведения платформы «1С:Предприятие»

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

Тип этого параметра зависит от контекста вызова:

  1. Неопределено — при обычном создании документа из меню или из списка без установленных отборов.
  2. Ссылка на объект (например, ДокументСсылка... или СправочникСсылка...) — при вводе документа на основании другого объекта.
  3. Структура — при создании нового документа из списка с активным отбором (в структуру помещаются отборы), а также при вызове метода Заполнить() или открытии формы с передачей параметра ЗначенияЗаполнения.

Ошибка происходит из-за некорректной проверки типа входящего параметра в коде модуля объекта. Если разработчик написал следующую конструкцию:


Если ЗначениеЗаполнено(ДанныеЗаполнения) Тогда
    ДокОснование = ДанныеЗаполнения.Ссылка;
КонецЕсли;

Функция ЗначениеЗаполнено() возвращает Истина не только для ссылок, но и для непустой структуры. Попытка обратиться к свойству Ссылка у объекта типа Структура вызывает исключение "Поле объекта не обнаружено (Ссылка)", так как в структуре отбора такого ключа нет.

Варианты исправления ошибки в коде

Рассмотрим несколько правильных способов обработки параметра ДанныеЗаполнения в процедуре ОбработкаЗаполнения.

Способ 1. Проверка типа данных на соответствие ссылкам документов

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


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
    
    Если Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(ДанныеЗаполнения)) Тогда
        ДокОснование = ДанныеЗаполнения.Ссылка;
    КонецЕсли;

КонецПроцедуры

Если необходимо проверить привязку к конкретному типу документа-основания, стандарт разработки 1С рекомендует использовать прямое сравнение типов через ТипЗнч():


Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
    ДокОснование = ДанныеЗаполнения;
ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
    // Обработка заполнения из структуры отбора списка
КонецЕсли;

Способ 2. Безопасное чтение свойств структуры

Посмотрим на пример, когда нужно безопасно извлечь значение из параметра, если там может оказаться структура. В этом случае следует использовать метод Свойство():


Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
    СсылкаОснование = Неопределено;
    Если ДанныеЗаполнения.Свойство("Ссылка", СсылкаОснование) Тогда
        ДокОснование = СсылкаОснование;
    КонецЕсли;
КонецЕсли;

Способ 3. Заполнение реквизитов документа из отбора списка

Проанализируем задачу, когда значения из отбора списка должны автоматически подставляться в соответствующие реквизиты нового документа. Чтобы задействовать полученную структуру отбора, используем процедуру ЗаполнитьЗначенияСвойств():


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)

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

КонецПроцедуры

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

← На главную