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