К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как вызвать функцию из модуля объекта

Как вызвать функцию из модуля объекта в 1С: Экспорт, обращение через ссылку, типичные ошибки и ограничения. Примеры кода для управляемого и обычного приложения.

Модуль объекта в 1С содержит обработчики событий и собственные процедуры и функции, относящиеся к конкретному объекту конфигурации — справочнику, документу, обработке. По умолчанию функции модуля объекта являются локальными: они доступны только внутри самого модуля. Чтобы вызвать такую функцию извне, её нужно объявить с ключевым словом Экспорт, а обращение выполнить через объектную ссылку, а не через менеджер объекта.

На практике задача возникает часто: например, нужно из модуля формы, общего модуля или другого документа получить результат расчёта, реализованного в модуле объекта. Разработчики часто ошибаются, пытаясь вызвать функцию через Справочники.Номенклатура.МояФункция() — такой вызов обращается к модулю менеджера, а не к модулю объекта, и заканчивается ошибкой «Метод объекта не обнаружен».

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

Как устроен модуль объекта и почему функция недоступна извне

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

Чтобы функция стала частью программного интерфейса объекта, в её объявлении добавляется Экспорт. После этого она доступна через экземпляр объекта, полученный методом ПолучитьОбъект(), или через переменную ЭтотОбъект внутри самого модуля.

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

Способ 1: вызов через ПолучитьОбъект() по ссылке

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

// Модуль объекта справочника "Номенклатура"

Функция ПолучитьОсновногоПоставщика() Экспорт

// логика поиска поставщика

Возврат Поставщик;

КонецФункции

Затем в месте вызова (например, в общем модуле или модуле другого объекта) получите объект и вызовите функцию:

ОбъектНоменклатуры = СсылкаНаНоменклатуру.ПолучитьОбъект();

Поставщик = ОбъектНоменклатуры.ПолучитьОсновногоПоставщика();

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

Порядок вызова функции из модуля объекта
  1. 1
    Откройте модуль объекта и добавьте Экспорт в объявление функции
  2. 2
    В месте вызова получите объект: Ссылка.ПолучитьОбъект()
  3. 3
    Вызовите функцию как метод объекта: Объект.ИмяФункции(Параметры)
  4. 4
    Проверьте результат и обработайте возможную ошибку блокировки

Способ 2: вызов из модуля формы объекта

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

&НаСервере

Функция РассчитатьНаСервере()

ОбъектДокумента = РеквизитФормыВЗначение("Объект");

Результат = ОбъектДокумента.РассчитатьИтоговуюСумму();

ЗначениеВРеквизитФормы(ОбъектДокумента, "Объект");

Возврат Результат;

КонецФункции

Обратное преобразование ЗначениеВРеквизитФормы нужно, если функция изменила реквизиты объекта и эти изменения должны отобразиться на форме. Если функция только возвращает значение без изменения объекта, обратное преобразование можно пропустить — это ускорит вызов.

В модуле формы элемента справочника или документа в обычном приложении объект доступен напрямую через реквизит формы, поэтому там достаточно вызвать Объект.ИмяФункции() без преобразований.

Способ 3: вызов из другого объекта или общего модуля

Из общего серверного модуля вызов аналогичен первому способу: получаете объект по ссылке и вызываете функцию. Типичный пример — обработка проведения одного документа обращается к функции другого документа-основания:

Если ЗначениеЗаполнено(ДокументОснование) Тогда

ОбъектОснования = ДокументОснование.ПолучитьОбъект();

СтатусОплаты = ОбъектОснования.ПолучитьСтатусОплаты();

КонецЕсли;

Здесь есть тонкость: такой вызов создаёт зависимость между объектами и увеличивает число чтений из базы. Если функция не использует данные конкретного экземпляра (например, универсальный расчёт по переданным параметрам), её правильнее разместить в общем модуле или модуле менеджера — тогда ПолучитьОбъект() не потребуется вовсе.

Маршрут решения

Где разместить функцию

Функция использует реквизиты конкретного экземпляра объектаОставьте её в модуле объекта с Экспорт и вызывайте через ПолучитьОбъект()
Функция не зависит от экземпляра и нужна в нескольких местахПеренесите её в общий модуль или модуль менеджера — вызов будет без чтения объекта из базы
Функция нужна только на формеРеализуйте её в серверной части модуля формы без обращения к модулю объекта

Ограничения и контекст выполнения

Модуль объекта выполняется только на сервере (и в толстом клиенте обычного приложения). В тонком и веб-клиенте объект недоступен, поэтому любой вызов экспортной функции модуля объекта из клиентского кода невозможен напрямую — только через серверные процедуры общих модулей с признаком «Вызов сервера» или через серверные методы формы.

Ещё одно ограничение: нельзя вызвать функцию модуля объекта, не создав и не получив экземпляр. Для нового объекта используется Справочники.Имя.СоздатьЭлемент() или Документы.Имя.СоздатьДокумент() — после создания экспортные функции доступны сразу, до записи в базу:

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДок.ЗаполнитьПоУмолчанию(); // экспортная процедура модуля объекта

НовыйДок.Записать();

Типичные ошибки при вызове

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

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

Типичные ошибки
01
Вызов Справочники.Имя.МояФункция() — так обращаются к модулю менеджера, а не к модулю объекта; результат — ошибка «Метод объекта не обнаружен»
02
Пропущено ключевое слово Экспорт — функция остаётся локальной и недоступна извне
03
Вызов из клиентской процедуры управляемой формы без серверной обёртки — объект недоступен на клиенте
04
ПолучитьОбъект() в цикле по тысячам ссылок — лишние чтения из базы и блокировки
05
Игнорирование ошибки блокировки при ПолучитьОбъект() в фоновых заданиях — обработка падает при параллельном редактировании

Как проверить, что вызов работает правильно

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

Дополнительно проверьте, что функция видит актуальные реквизиты объекта: при вызове через ПолучитьОбъект() данные читаются из базы, а при вызове из формы через РеквизитФормыВЗначение — из данных формы, которые могут отличаться от сохранённых. Это принципиально разные состояния объекта, и путать их нельзя.

Контрольные точки

Как проверить результат

Функция объявлена с Экспорт
Норма

В объявлении есть ключевое слово Экспорт после списка параметров

Тревожный признак

Слово Экспорт отсутствует — функция доступна только внутри модуля

Точка вызова
Норма

Вызов через экземпляр: Ссылка.ПолучитьОбъект().Функция()

Тревожный признак

Вызов через менеджер: Справочники.Имя.Функция()

Поведение в отладчике
Норма

Точка останова в функции срабатывает, реквизиты объекта заполнены

Тревожный признак

Отладчик не заходит в функцию или реквизиты пустые

Контекст выполнения
Норма

Вызов выполняется на сервере

Тревожный признак

Вызов из клиентской процедуры без серверной обёртки

FAQ

Можно ли вызвать функцию модуля объекта без ПолучитьОбъект()?

Только если экземпляр объекта уже существует в текущем контексте: внутри самого модуля объекта (через ЭтотОбъект), при создании нового объекта через СоздатьЭлемент()/СоздатьДокумент() или после преобразования данных формы. По одной лишь ссылке без получения объекта вызвать функцию нельзя.

Чем модуль объекта отличается от модуля менеджера?

Модуль объекта работает с конкретным экземпляром и имеет доступ к его реквизитам напрямую. Модуль менеджера не привязан к экземпляру: его экспортные функции вызываются через Справочники.Имя.Функция() и обычно принимают ссылку параметром. Для операций над множеством объектов модуль менеджера предпочтительнее.

Почему возникает ошибка «Метод объекта не обнаружен»?

Три основные причины: функция объявлена без ключевого слова Экспорт; вызов идёт через менеджер объекта, а функция находится в модуле объекта (или наоборот); конфигурация базы данных не обновлена после изменения модуля. Проверьте все три пункта по порядку.

Можно ли вызвать функцию модуля объекта из внешней обработки?

Да, если внешняя обработка выполняется на сервере или в толстом клиенте: получите объект по ссылке через ПолучитьОбъект() и вызовите экспортную функцию. В управляемом приложении с тонким клиентом код должен выполняться в серверной процедуре общего модуля или серверной части формы обработки.

Когда функцию лучше вынести из модуля объекта в общий модуль?

Когда функция не использует реквизиты конкретного экземпляра, вызывается из многих мест или нужна на клиенте. Общий модуль с признаками «Сервер» и «Вызов сервера» избавляет от необходимости читать объект из базы ради одного расчёта и упрощает поддержку кода.

Работает ли вызов в фоновом задании?

Да, фоновое задание выполняется на сервере, поэтому ПолучитьОбъект() и вызов экспортной функции работают. Учтите риск блокировок: если пользователь редактирует тот же объект, ПолучитьОбъект() завершится ошибкой — оборачивайте вызов в попытку и предусмотрите повтор.

Итог

Что важно запомнить

Функция модуля объекта вызывается извне только с ключевым словом Экспорт и только через экземпляр объекта: Ссылка.ПолучитьОбъект().ИмяФункции(). Вызов через менеджер объекта, отсутствие Экспорт и попытка вызова с клиента — три главные причины ошибок. Если функция не зависит от экземпляра, размещайте её в общем модуле.