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

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

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

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

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

Главная ошибка новичков — попытка обратиться к функции через ссылку вида Документы.РеализацияТоваров.МояФункция(). Ссылка — это только идентификатор записи в базе, она не содержит исполняемого кода. Чтобы получить доступ к экспортным функциям модуля объекта, нужно создать объект документа методом ПолучитьОбъект() или СоздатьДокумент().

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

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

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

Пример объявления экспортной функции в модуле объекта:

bsl
Функция РассчитатьСуммуСоСкидкой(ПроцентСкидки) Экспорт
	СуммаДокумента = Товары.Итог("Сумма");
	Возврат СуммаДокумента * (100 - ПроцентСкидки) / 100;
КонецФункции

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

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

Вызов функции на сервере через ПолучитьОбъект

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

Порядок вызова на сервере
  1. 1
    Убедитесь, что функция в модуле объекта объявлена с Экспорт
  2. 2
    Получите объект: ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект()
  3. 3
    Вызовите функцию: Результат = ДокОбъект.МояФункция(Параметр1)
  4. 4
    Если функция меняла данные объекта — выполните ДокОбъект.Записать()
  5. 5
    Проверьте результат и обработайте возможные исключения

Пример кода вызывающей стороны:

bsl
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ИтоговаяСумма = ДокОбъект.РассчитатьСуммуСоСкидкой(10);
// Если функция изменила табличные части:
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

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

Вызов функции из формы документа

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

Рабочий способ — серверная процедура формы с преобразованием данных формы в объект:

bsl
&НаСервере
Процедура ПересчитатьНаСервере()
	ДокОбъект = РеквизитФормыВЗначение("Объект");
	Итог = ДокОбъект.РассчитатьСуммуСоСкидкой(ПроцентСкидки);
	ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

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

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

Вызов функции для нового, ещё не записанного документа

Если документа в базе ещё нет, объект создаётся через менеджер документа:

bsl
НовыйДок = Документы.РеализацияТоваров.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДатаСеанса();
// заполнение реквизитов и табличных частей
Итог = НовыйДок.РассчитатьСуммуСоСкидкой(5);
НовыйДок.Записать();

Экспортные функции модуля объекта доступны сразу после СоздатьДокумент() — записывать документ перед вызовом не требуется. Это удобно для расчётов «на лету» перед проведением.

Альтернатива: модуль менеджера и общие модули

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

bsl
// В модуле менеджера документа:
Функция РассчитатьСуммуСоСкидкой(СсылкаНаДокумент, ПроцентСкидки) Экспорт
	// расчёт через запрос по ссылке
КонецФункции

// Вызов откуда угодно на сервере:
Итог = Документы.РеализацияТоваров.РассчитатьСуммуСоСкидкой(Ссылка, 10);

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

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

Логика, неразрывно связанная с данными конкретного экземпляра и его табличными частями. Требует ПолучитьОбъект() при внешнем вызове.

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

Операции над документами по ссылке: расчёты, печать, подбор данных. Вызывается без создания объекта, удобно для массовых операций.

Общий модуль

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

Типичные ошибки и их диагностика

Большинство проблем при вызове функции модуля документа сводится к нескольким повторяющимся ситуациям.

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

Отдельная группа ошибок — контекст исполнения. Если общий модуль имеет флажки «Клиент» и «Сервер», но не «Вызов сервера», обращение к нему с клиента приведёт к ошибке. Проверяйте директивы компиляции (&НаСервере, &НаКлиенте) и свойства модулей.

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

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

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

Конфигуратор не сообщает об ошибках при проверке модуля

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

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

Вызов в отладчике
Норма

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

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

Исполнение не заходит в функцию — вызов идёт не по тому объекту

Данные после вызова
Норма

Изменения, сделанные функцией, сохранены после Записать()

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

Данные на месте в объекте, но в базе старые — пропущен Записать()

FAQ

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

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

Почему ПолучитьОбъект() возвращает Неопределено?

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

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

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

Нужно ли записывать документ, если функция только считает значение?

Нет. Если функция выполняет только расчёт и не изменяет реквизиты или табличные части объекта, записывать документ не требуется — объект можно просто уничтожить, освободив память.

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

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

Итог

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

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