Как правильно реализовать программный ввод на основании и избежать ошибки «Поле объекта не обнаружено»?

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

При разработке конфигураций на управляемых формах 1С часто возникает необходимость открыть конкретную (не основную) форму нового документа и одновременно заполнить её реквизиты данными из документа-основания. При реализации такого сценария разработчики нередко сталкиваются с ошибкой времени выполнения:

Ошибка при выполнении обработчика - 'ОбработкаЗаполнения'
Поле объекта не обнаружено (ИмяРеквизита)

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

Анализ исходной проблемы и причины ошибки

Рассмотрим типовой сценарий, в котором возникает ошибка. Разработчик пытается открыть форму документа ЗаказНаряд из документа ЗаявкаНаРемонт с передачей параметров:


&НаКлиенте
Процедура ЗаказНаряд(Команда, Элемент)
    ЗначенияЗаполнения = Новый Структура;
    ЗначенияЗаполнения.Вставить("Владелец", Объект.Ссылка);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ЗначенияЗаполнения", ЗначенияЗаполнения);
    
    ОткрытьФорму("Документ.ЗаказНаряд.Форма.ФормаДокументаБН", ПараметрыФормы, Элемент);
КонецПроцедуры

В модуле объекта открываемого документа в процедуре ОбработкаЗаполнения написан следующий код:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если ДанныеЗаполнения <> Неопределено И ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
        // Заполнение шапки
        Автомобиль = ДанныеЗаполнения.Автомобиль;
        Автор = ДанныеЗаполнения.Автор;
        ВидРемонта = ДанныеЗаполнения.ВидРемонта;
    КонецЕсли;
КонецПроцедуры

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

В процедуре на клиенте в структуру был добавлен только один ключ — "Владелец". В обработчик ОбработкаЗаполнения в параметр ДанныеЗаполнения приходит именно эта структура. Прямое обращение через точку к свойству ДанныеЗаполнения.Автомобиль вызывает исключение, так как такого ключа в структуре просто не существует, независимо от того, есть ли одноименный реквизит у самого документа в метаданных.

Кроме того, отдельный вызов метода Документы.ЗаказНаряд.СоздатьДокумент() на сервере перед открытием формы является избыточным: созданный локальный объект никуда не передается и сразу уничтожается, создавая лишнюю нагрузку на сервер.

Рассмотрим несколько надежных способов реализации ввода на основании и заполнения новой формы.

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

Если в процедуру ОбработкаЗаполнения передается структура с произвольным набором полей, нельзя обращаться к свойствам напрямую через точку. Рассмотрим безопасные варианты работы со структурой:

  1. Использование метода ЗаполнитьЗначенияСвойств:

    Метод автоматически копирует значения только тех свойств, имена которых совпадают с реквизитами документа, и полностью игнорирует отсутствующие ключи:

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

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

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

Способ 2. Передача ссылки на документ-основание (Штатный механизм)

Если логика заполнения нового документа строится на чтении реквизитов документа-источника, правильнее передавать не структуру, а саму ссылку на исходный документ. Для этого в параметрах формы используется стандартный параметр Основание (или ЗначениеЗаполнения):


&НаКлиенте
Процедура ЗаказНаряд(Команда, Элемент)
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Основание", Объект.Ссылка);
    
    ОткрытьФорму("Документ.ЗаказНаряд.Форма.ФормаДокументаБН", ПараметрыФормы, Элемент);
КонецПроцедуры

В этом случае платформа автоматически передаст ссылку исходного документа в обработчик ОбработкаЗаполнения. В модуле объекта принимающего документа мы проверяем тип ссылки и считываем данные:


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

Способ 3. Переопределение формы через модуль менеджера

Если цель состоит лишь в том, чтобы при вводе на основании открывалась нестандартная форма (например, ФормаДокументаБН вместо основной), нет необходимости переписывать команды на клиенте. Можно использовать стандартную команду ввода на основании, переопределив открываемую форму в событии ОбработкаПолученияФормы модуля менеджера документа:


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

Такой подход сохраняет типовую архитектуру платформы 1С:Предприятие, избавляет от дублирования клиентского кода вызова форм и централизует логику выбора нужного интерфейса.

← На главную