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