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