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

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

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

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

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

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

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

Где находится модуль объекта и чем он отличается от других модулей

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

Ключевое отличие от общего модуля в том, что у модуля объекта нет глобального имени для вызова. Общий модуль «РаботаСЦенами» вызывается как РаботаСЦенами.ПолучитьЦену() откуда угодно, а функция модуля объекта требует сначала материализовать объект в памяти. Это сделано намеренно: логика модуля объекта почти всегда завязана на данные конкретного экземпляра.

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

Как объявить функцию с Экспорт

Откройте модуль объекта и добавьте функцию с ключевым словом Экспорт после списка параметров. Например, в модуле объекта документа «ЗаказКлиента»:

Функция ПолучитьСуммуСоСкидкой(ПроцентСкидки) Экспорт

СуммаДокумента = ЭтотОбъект.Товары.Итог("Сумма");

Возврат СуммаДокумента * (100 - ПроцентСкидки) / 100;

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

Слово Экспорт ставится после закрывающей скобки параметров, а не перед ключевым словом «Функция» — это частая синтаксическая ошибка. Конструкция Экспорт Функция ... вызовет ошибку компиляции модуля.

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

Вызов функции через создание объекта

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

// Новый объект

НовыйДокумент = Документы.ЗаказКлиента.СоздатьДокумент();

Сумма = НовыйДокумент.ПолучитьСуммуСоСкидкой(10);

// Существующий объект по ссылке

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

Сумма = ОбъектДокумента.ПолучитьСуммуСоСкидкой(10);

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

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

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

Вызов из модуля формы

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

Стандартный приём — серверная процедура формы, в которой данные преобразуются в объект через РеквизитФормыВЗначение:

&НаСервере

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

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

Возврат ОбъектДокумента.ПолучитьСуммуСоСкидкой(ПроцентСкидки);

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

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

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

Вызов из общего модуля и других объектов

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

Процедура ПересчитатьИтогиЗаказов() Экспорт

Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.ЗаказКлиента");

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

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

Итог = ОбъектДокумента.ПолучитьСуммуСоСкидкой(5);

// дальнейшая обработка результата

КонецЦикла;

КонецПроцедуры

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

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

Альтернативы: когда функцию лучше разместить не в модуле объекта

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

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

Модуль объекта

Функция — поведение конкретного экземпляра, использует ЭтотОбъект. Требует создания объекта при вызове.

Модуль менеджера

Функция работает с типом в целом: поиск, подбор, печать по ссылке. Вызывается через Документы.Имя.Функция() без создания объекта.

Общий модуль

Универсальная логика для разных типов объектов. Доступна отовсюду, но не имеет контекста ЭтотОбъект.

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

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

Проверка результата и типичные ошибки

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

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

Как проверить корректность вызова

Компиляция модуля
Норма

Конфигуратор не сообщает об ошибках при сохранении

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

Ошибка «Процедура или функция не определена» — нет Экспорт или неверное имя

Отладчик
Норма

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

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

Точка не срабатывает — объект не создан или вызов идёт по другой ветке кода

Возвращаемое значение
Норма

Функция возвращает значение ожидаемого типа

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

Возвращается Неопределено — в функции нет Возврат на всех ветках

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

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

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

Итог

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

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

Частые вопросы

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

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

Почему возникает ошибка «Процедура или функция с указанным именем не определена»?

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

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

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

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

Да, но с учётом контекста. Команда формы с директивой &НаКлиенте не имеет доступа к модулю объекта — нужен серверный вызов. Сделайте серверную процедуру (в форме или в серверном общем модуле), получите объект и вызовите функцию там, а результат верните в клиентскую процедуру команды.

Чем вызов функции модуля объекта отличается от вызова функции модуля менеджера?

Функция модуля менеджера вызывается через менеджер типа — Справочники.Номенклатура.МояФункция() — и не требует экземпляра объекта, но не имеет доступа к ЭтотОбъект. Функция модуля объекта требует экземпляр, зато работает с его реквизитами и табличными частями напрямую. Выбор зависит от того, нужны ли функции данные конкретного объекта.

Безопасно ли добавлять свои функции в модуль объекта типовой конфигурации?

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