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