Как проверить наличие реквизита формы и избежать ошибки «Поле объекта не обнаружено» в 1С?

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

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

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

Почему возникает ошибка при обращении на клиенте

Проанализируем ситуацию: объект УправляемаяФорма на тонком клиенте не предоставляет динамического доступа к свойствам через методы вроде Свойство(), как это происходит со структурой. Если реквизита с именем Объект у формы-владельца нет (например, вызов происходит из формы списка, обработки или формы с другим именем главного реквизита), клиентский контекст моментально выдает фатальное исключение.

Кроме того, обращение к свойству Родитель у элемента ТаблицаФормы зависит от текущей структуры элементов формы. Если таблица переместится внутри группы или страницы, свойство Родитель вернет элемент ГруппаФормы, у которого вовсе нет свойства ВладелецФормы.

Решение 1. Передача данных через параметры формы (Рекомендуемый подход)

Самым надежным и архитектурно верным решением является отказ от прямой зависимости подчиненной формы от внутренней структуры формы-владельца. Вместо обращения к владельцу передадим необходимые флаги или ссылки в параметрах при открытии формы.

Разберем по шагам, как это реализовать:

  1. В открываемой форме добавим параметр (например, РежимТолькоПросмотрВладельца с типом Булево или параметр для передачи ссылки).
  2. В форме-источнике при открытии подчиненной формы передадим этот параметр в структуре параметров.
  3. В форме-получателе обработаем этот параметр в событии ПриСозданииНаСервере.

Пример обработки параметра на сервере в открываемой форме:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Если Параметры.Свойство("ТолькоПросмотрВладельца") И Параметры.ТолькоПросмотрВладельца Тогда
        Элементы.ВладелецКарты.ТолькоПросмотр = Истина;
    КонецЕсли;

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

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

Решение 2. Проверка имени формы-владельца

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

Рассмотрим пример клиентского кода с проверкой имени формы:


&НаКлиенте
Процедура ПриОткрытии(Отказ)

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

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

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

Решение 3. Использование функций БСП для безопасного чтения реквизитов

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

Посмотрим на пример применения функции БСП на клиенте:


&НаКлиенте
Процедура ПриОткрытии(Отказ)

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

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

Если реквизит по указанному пути отсутствует, функция вернет Неопределено, что предохранит систему от падения с ошибкой «Поле объекта не обнаружено».

← На главную