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