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