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