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