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

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

Как вставить функцию в процедуру 1С

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

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

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

Ниже разобраны синтаксис вызова, передача параметров, работа с результатом, экспортные функции общих модулей и частые ошибки, из-за которых вызов не работает.

Как устроен вызов функции из процедуры

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

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

Функция РассчитатьСкидку(Сумма)

Если Сумма > 100000 Тогда

Возврат Сумма * 0.1;

Иначе

Возврат 0;

КонецЕсли;

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

Процедура ПриЗаписи(Отказ)

Скидка = РассчитатьСкидку(ЭтотОбъект.СуммаДокумента);

Если Скидка > 0 Тогда

Сообщить("Применена скидка: " + Скидка);

КонецЕсли;

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

Порядок объявления внутри модуля не важен: функцию можно описать ниже процедуры, которая её вызывает. Платформа разрешает ссылки при компиляции модуля целиком.

Как передать параметры и получить результат

Параметры перечисляются в скобках через запятую в том же порядке, в каком они объявлены в функции. Если параметр в объявлении имеет значение по умолчанию, его можно опустить при вызове.

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

Функция ПолучитьЦену(Номенклатура, Дата = Неопределено)

Если Дата = Неопределено Тогда

Дата = ТекущаяДатаСеанса();

КонецЕсли;

// ... запрос к регистру цен

Возврат Цена;

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

Процедура ЗаполнитьЦены()

Цена = ПолучитьЦену(СтрокаТовара.Номенклатура);

// второй параметр не передан — подставится текущая дата

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

Если вызвать функцию как обычную инструкцию, не используя результат (РассчитатьСкидку(Сумма);), платформа выдаст ошибку: функция не может вызываться как процедура. Результат нужно либо присвоить, либо использовать в выражении.

Порядок действий
  1. 1
    Объявите функцию в модуле: Функция Имя(Параметры) ... Возврат Значение; КонецФункции
  2. 2
    Внутри процедуры напишите вызов: Переменная = Имя(Аргумент);
  3. 3
    Если функция в общем модуле — добавьте Экспорт и вызывайте через имя модуля: ОбщегоНазначения.Имя(Аргумент)
  4. 4
    Проверьте тип возвращаемого значения и обработайте случай Неопределено
  5. 5
    Выполните синтаксическую проверку модуля и протестируйте вызов на реальных данных

Вызов функции из общего модуля

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

// Общий модуль РасчетыСервер

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

Возврат Сумма * Ставка / (100 + Ставка);

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

Вызов из процедуры любого другого модуля выполняется через имя общего модуля:

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

НДС = РасчетыСервер.РассчитатьНДС(СуммаДокумента, 20);

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

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

Вставка вызова в условия и выражения

Результат функции можно использовать не только в присваивании. Вызов допустим везде, где ожидается значение: в условии Если, в цикле, в аргументах другой функции, в строковом выражении.

Процедура ПроверитьДокумент(Документ)

Если НЕ ПраваДоступа.ЕстьПравоПроведения(Документ) Тогда

ВызватьИсключение "Недостаточно прав";

КонецЕсли;

Сообщить("Итог: " + Формат(РассчитатьИтог(Документ), "ЧДЦ=2"));

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

Такой стиль сокращает количество промежуточных переменных. Однако не стоит вкладывать вызовы друг в друга глубже двух-трёх уровней: читаемость падает, а отладка усложняется — точку останова на промежуточный результат поставить нельзя.

Типичные ошибки при вызове функции

Первая и самая распространённая — «Процедура или функция с указанным именем не определена». Причины: опечатка в имени, отсутствие Экспорт в общем модуле, вызов серверной функции из клиентского контекста либо функция объявлена в модуле объекта, а вызывается из формы.

Вторая группа ошибок связана с параметрами: несовпадение количества аргументов, передача значения несовместимого типа, пропуск обязательного параметра. Платформа проверяет число параметров при компиляции, но тип — только в момент выполнения, поэтому ошибка может всплыть поздно.

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

Типичные ошибки
01
Вызов функции без использования результата — синтаксическая ошибка, функция не может выступать как оператор
02
Отсутствие слова Экспорт в общем модуле — функция невидима извне, ошибка «не определена»
03
Вызов серверной функции из клиентской процедуры без флага «Вызов сервера» — ошибка выполнения
04
Отсутствие Возврат в одной из веток — функция возвращает Неопределено и ломает расчёты ниже
05
Изменение параметра, переданного по ссылке, без намерения — побочные эффекты в вызывающем коде

Как проверить, что вызов работает правильно

Минимальная проверка — синтаксический контроль модуля: меню «Конфигурация — Проверка конфигурации» или кнопка проверки модуля в редакторе кода. Он отловит несуществующие имена и ошибки в количестве параметров.

Для проверки логики используйте отладчик: поставьте точку останова на строке вызова, шагните внутрь функции клавишей F11 и посмотрите значения параметров и результат через табло. Убедитесь, что функция доходит до нужного Возврат, а не выходит по ветке без возврата.

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

Контрольные точки

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

Синтаксическая проверка модуля
Норма

Ошибок нет, вызов распознан

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

«Процедура или функция не определена» — проверьте имя и Экспорт

Значение после вызова
Норма

Переменная содержит ожидаемый тип и значение

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

Неопределено — функция вышла без Возврат

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

Управление проходит через нужный Возврат

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

Функция завершается по другой ветке или падает с исключением

Когда выносить код в функцию, а когда оставить в процедуре

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

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

Итог

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

Функция вставляется в процедуру вызовом по имени с параметрами, результат присваивается переменной или используется в выражении. Для вызова из других модулей нужен общий модуль с Экспорт, для клиент-серверного взаимодействия — корректные флаги модуля. Проверяйте наличие Возврат во всех ветках и обрабатывайте Неопределено.

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

Можно ли вызвать процедуру внутри функции?

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

Почему возникает ошибка «Процедура или функция с указанным именем не определена»?

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

Как передать в функцию таблицу значений или массив?

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

Что вернёт функция, если ни один Возврат не сработал?

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

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

Напрямую — никак, модуль объекта и модуль формы изолированы. Варианты: вынести функцию в общий модуль, либо в форме получить объект через РеквизитФормыВЗначение("Объект") и вызвать метод у полученного значения, если он экспортный.