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

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

Как обратиться к функции в общем модуле 1С

Как вызвать функцию из общего модуля 1С: синтаксис обращения, флаги Сервер и Вызов сервера, экспортные функции, типичные ошибки и примеры кода.

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

Обращение к функции общего модуля выполняется по простой схеме: ИмяМодуля.ИмяФункции(Параметры). Однако на практике результат зависит от нескольких условий: функция должна быть объявлена с ключевым словом Экспорт, модуль должен компилироваться в нужном контексте (клиент или сервер), а при вызове серверной функции с клиента у модуля должен быть установлен флаг «Вызов сервера». Несоблюдение любого из этих условий приводит к ошибке «Процедура или функция с указанным именем не определена» или «Метод объекта не обнаружен».

Синтаксис обращения к функции общего модуля

Базовая форма вызова состоит из имени общего модуля, точки и имени функции со списком параметров в скобках. Имя модуля указывается так, как оно задано в дереве конфигурации, без кавычек и без префиксов:

// Вызов функции ПолучитьСтавкуНДС() из общего модуля РаботаСНалогами

Ставка = РаботаСНалогами.ПолучитьСтавкуНДС(ДатаДокумента);

// Вызов без параметров

ТекущаяОрганизация = НастройкиСистемы.ОрганизацияПоУмолчанию();

// Вызов с несколькими параметрами

СуммаПрописью = СтроковыеФункции.СуммаПрописью(СуммаДокумента, Валюта, "рус");

Если функция возвращает значение, его нужно присвоить переменной или использовать в выражении — иначе результат будет потерян. Если в модуле объявлена процедура (а не функция), она вызывается как отдельный оператор, без присваивания: Журналирование.ЗаписатьСобытие(ТекстСобытия);.

Точка с запятой в конце оператора обязательна. Параметры передаются в том порядке, в котором они объявлены в функции; пропущенные параметры в середине списка заменяются запятыми: Модуль.Функция(Парам1, , Парам3);.

Как подготовить функцию в общем модуле

Чтобы функция была видна извне, при её объявлении после списка параметров ставится ключевое слово Экспорт. Без него функция остаётся приватной и доступна только внутри самого модуля — попытка обратиться к ней снаружи вызовет ошибку компиляции.

// Общий модуль РасчетЦен

Функция РассчитатьЦенуСНДС(ЦенаБезНДС, СтавкаНДС) Экспорт

Возврат ЦенаБезНДС * (1 + СтавкаНДС / 100);

КонецФункции

// Внутренняя вспомогательная функция — снаружи недоступна

Функция ОкруглитьКопейки(Значение)

Возврат Окр(Значение, 2);

КонецФункции

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

Порядок действий
  1. 1
    Создайте общий модуль в ветке «Общие → Общие модули» и задайте ему имя
  2. 2
    Установите флаги контекста: «Сервер» для серверной логики, «Клиент (управляемое приложение)» для клиентской
  3. 3
    Объявите функцию с ключевым словом Экспорт после списка параметров
  4. 4
    Сохраните конфигурацию и обновите конфигурацию базы данных (F7)
  5. 5
    Вызовите функцию из нужного объекта: ИмяМодуля.ИмяФункции(Параметры)

Настройка флагов контекста: Сервер, Клиент, Вызов сервера

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

ФлагЧто означаетКогда нужен
СерверКод компилируется на сервере 1СЗапросы к базе, транзакции, любая работа с данными
Клиент (управляемое приложение)Код доступен в клиентском контексте формИнтерфейсная логика, работа с файлами на компьютере пользователя
Вызов сервераРазрешает обращение к серверному модулю с клиентаОбязателен, если клиентский код вызывает серверную функцию
Клиент (обычное приложение)Доступ в обычных формахТолько для устаревшего обычного приложения
Привилегированный режимКод выполняется без проверки правКогда вызов должен работать независимо от прав пользователя

Типовая схема для управляемого приложения: серверный модуль с флагами «Сервер» и «Вызов сервера» содержит всю работу с базой данных; клиентские модули форм вызывают его функции напрямую. Если флаг «Вызов сервера» не установлен, при попытке обращения с клиента возникнет ошибка «Вызов сервера запрещен» или функция будет просто не видна.

Вызов серверной функции с клиента

В управляемых формах код разделён на клиентский и серверный контексты, и платформа не позволяет клиенту напрямую выполнять запросы к базе. Поэтому вся работа с данными выносится в серверные общие модули, а клиент обращается к ним как к посреднику.

// Клиентский модуль формы документа

&НаКлиенте

Процедура ПересчитатьИтоги(Команда)

Итог = ДокументыСервер.РассчитатьИтогДокумента(Объект.Ссылка);

Элементы.ИтоговаяСумма.Заголовок = Строка(Итог);

КонецПроцедуры

Здесь ДокументыСервер — общий модуль с флагами «Сервер» и «Вызов сервера». Важное ограничение: между клиентом и сервером передаются только сериализуемые типы данных. Можно передавать примитивные типы, структуры, массивы, ссылки на объекты. Нельзя передавать объекты типа Запрос, РезультатЗапроса, ТабличныйДокумент в открытом виде и другие несериализуемые значения — платформа выдаст ошибку передачи данных.

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

Если в клиентской процедуре нужно получить с сервера несколько значений (ставку НДС, валюту, склад по умолчанию), не делайте три отдельных вызова. Создайте одну серверную функцию, возвращающую структуру со всеми значениями, — это заметно быстрее на медленных соединениях.
ПЗ
Практическое замечание

Обращение из модуля объекта, формы и внешнего соединения

Из модуля объекта (например, документа) общие модули вызываются без каких-либо ограничений — код объекта исполняется на сервере, поэтому серверные модули доступны напрямую:

// Модуль объекта документа «РеализацияТоваров»

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Если НЕ ПроверкаЗаполнения.ДокументКорректен(ЭтотОбъект) Тогда

Отказ = Истина;

Возврат;

КонецЕсли;

КонецПроцедуры

Из модуля формы обращение зависит от директивы компиляции: в блоке &НаКлиенте доступны только клиентские модули и серверные с флагом «Вызов сервера», в блоке &НаСервере — все серверные модули. Внешние обработки работают по тем же правилам: их серверный код видит серверные общие модули конфигурации.

Через COM-соединение или внешнее соединение общие модули доступны как методы объекта соединения: Соединение.ИмяМодуля.ИмяФункции(Параметры). Это работает, если модуль серверный, а у пользователя, под которым установлено соединение, есть права на выполнение.

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

Большинство проблем при обращении к функциям общих модулей сводится к нескольким повторяющимся причинам. Ошибка «Процедура или функция с указанным именем не определена» означает, что платформа не нашла экспортную функцию: либо пропущено слово Экспорт, либо опечатка в имени, либо модуль не компилируется в текущем контексте. Ошибка «Переменная не определена (ИмяМодуля)» говорит о том, что сам модуль недоступен в данном контексте — проверяйте флаги «Сервер» / «Клиент».

Отдельный случай — циклические ссылки: модуль А вызывает функцию модуля Б, а модуль Б — функцию модуля А. Платформа при компиляции выдаёт ошибку «Обнаружена циклическая ссылка». Решение — вынести общую часть в третий модуль или пересмотреть распределение логики.

Типичные ошибки
01
Пропущено ключевое слово Экспорт — функция невидима снаружи, ошибка «не определена»
02
Не установлен флаг «Вызов сервера» у серверного модуля — клиент не может обратиться к функции
03
Опечатка в имени модуля или функции — встроенный язык чувствителен к точному написанию, хотя и не к регистру
04
Передача несериализуемых типов (Запрос, РезультатЗапроса) между клиентом и сервером — ошибка передачи данных
05
Вызов функции без обновления конфигурации базы данных после изменений — в пользовательском режиме работает старый код
06
Циклические вызовы между общими модулями — ошибка компиляции конфигурации
Контрольные точки

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

Функция объявлена в общем модуле
Норма

После списка параметров стоит слово Экспорт

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

Экспорт отсутствует — функция приватная

Флаги контекста модуля
Норма

Сервер + Вызов сервера для серверной логики, вызываемой с клиента

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

Только Сервер, а вызов идёт из клиентской процедуры

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

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

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

Выполнение падает с ошибкой до входа в функцию

Конфигурация обновлена
Норма

После изменений выполнено обновление конфигурации БД (F7)

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

Код изменён, но база работает на старой версии

Рекомендации по организации общих модулей

Группируйте функции в модули по предметной области, а не по типу операций: «РаботаСЦенами», «ОбменДанными», «ПечатьДокументов» читаются лучше, чем один гигантский модуль «ОбщиеПроцедуры» на несколько тысяч строк. В типовых конфигурациях принят суффиксный подход к именам: «...Сервер», «...Клиент», «...ВызовСервера» — он сразу показывает контекст исполнения.

Если функция используется только внутри одного объекта (например, только в конкретном документе), размещать её в общем модуле не нужно — оставьте её в модуле объекта. Общий модуль оправдан, когда код реально переиспользуется минимум в двух-трёх местах или когда требуется отдельный контекст исполнения (привилегированный режим, серверный вызов).

Итог

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

Вызов строится как ИмяМодуля.ИмяФункции(Параметры). Три обязательных условия: слово Экспорт у функции, правильные флаги контекста модуля и флаг «Вызов сервера» при обращении с клиента. Серверные вызовы из клиентского кода минимизируйте, передавая данные пакетами через структуры.

Частые вопросы

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

Да, общие модули свободно вызывают функции друг друга при условии совместимости контекстов: клиентский модуль не может обратиться к серверному без флага «Вызов сервера». Главное ограничение — недопустимость циклических ссылок, когда два модуля вызывают друг друга.

Почему функция видна в конфигураторе, но в режиме предприятия возникает ошибка?

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

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

Менеджер объекта (например, Справочники.Номенклатура.Метод()) привязан к конкретному типу данных и содержит логику этого объекта. Общий модуль не привязан ни к чему и подходит для сквозной логики. Если функция работает исключительно с одним типом объектов, логичнее разместить её в модуле менеджера этого объекта.

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

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

Что делать, если нужно вернуть из серверной функции таблицу значений?

Таблица значений не передаётся между клиентом и сервером напрямую. Преобразуйте её в массив структур на сервере и верните этот массив, а на клиенте при необходимости соберите данные обратно. Либо используйте реквизит формы типа «ТаблицаЗначений» и заполняйте его в серверной процедуре формы.