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