Как исправить ошибку «Ошибка при вызове метода контекста ПолучитьОбъект()» в 1С?

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

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

Почему возникает ошибка «Элемент не выбран»?

Рассмотрим ситуацию, с которой столкнулся автор темы. В коде выполнялась проверка ссылки на пустоту, после чего вызывался метод ПолучитьОбъект(). Однако из-за невнимательности в логическом условии (пропуске или неверном использовании отрицания НЕ) код пытался получить объект от пустой ссылки.

В платформе 1С поведение метода ПолучитьОбъект() зависит от состояния ссылки, к которой он применяется:

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

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


Если НЕ Ссылка.ГрафикТО.Пустая() Тогда
    ГрафОбъект = Ссылка.GraphicTO.ПолучитьОбъект();
    Если ГрафОбъект <> Неопределено Тогда
        // Безопасная работа с объектом
    КонецЕсли;
КонецЕсли;

Анализ синтаксических ошибок в исходном коде

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

  1. Избыточное обращение через точку: Ссылка.ГрафикТО.Ссылка.ПолучитьОбъект(). Реквизит ГрафикТО сам по себе уже является ссылкой. Повторное обращение к свойству Ссылка избыточно и замедляет работу системы. Правильный вариант: Ссылка.ГрафикТО.ПолучитьОбъект().
  2. Вызов несуществующих методов у табличных частей: В сообщении №17 предлагался код с конструкцией Граф.ТехОбсл.Пустая(). У объекта табличной части в 1С нет метода Пустая(). Чтобы проверить, содержит ли табличная часть строки, необходимо использовать метод Количество():
    
    Если Граф.ТехОбсл.Количество() > 0 Тогда
        // Обработка строк
    КонецЕсли;
    
  3. Неоптимальное позиционирование метода записи: Вызов метода Записать() внутри цикла обхода строк табличной части приводит к тому, что документ перезаписывается на каждой итерации. Это создает колоссальную нагрузку на СУБД. Метод Записать() необходимо вызывать строго после завершения цикла обхода.

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


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

Критическая архитектурная ошибка: запись сторонних объектов при проведении

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

Выделим основные причины, почему так делать нельзя:

Рекомендуемые варианты решения задачи

Как же правильно реализовать бизнес-логику, при которой проведение одного документа должно отражаться на состоянии другого?

Вариант 1. Использование регистров сведений (Рекомендуемый стандарт разработки 1С)

Вместо непосредственного изменения табличной части документа ГрафикТО, мы должны использовать механизмы платформы по их прямому назначению. Для хранения состояний и отметок о выполнении задач идеально подходит Регистр сведений (например, независимый регистр «Выполнение графиков ТО»).

Рассмотрим схему реализации:

  1. При проведении документа АктТО мы делаем запись в регистр сведений, указывая в качестве измерений ГрафикТО и Маршрут, а в качестве ресурса — признак выполнения и ссылку на сам АктТО.
  2. В форме документа ГрафикТО или в связанных отчетах мы не храним эти данные физически в табличной части, а динамически считываем их простым запросом к регистру сведений при открытии или формировании отчета. При этом сам документ ГрафикТО остается нетронутым, не перезаписывается и не блокирует работу других пользователей.

Вариант 2. Вынос записи стороннего объекта за рамки транзакции проведения

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

← На главную