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

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

Обращение к процедуре как к функции в 1С: причины и решение

Почему в 1С нельзя обратиться к процедуре как к функции, как исправить ошибку компиляции, отличия процедур и функций, примеры кода и типичные ошибки.

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

Типичная ситуация выглядит так: в модуле объявлена процедура ЗаполнитьДанные(), а в другом месте написано Результат = ЗаполнитьДанные();. Конфигуратор выдаёт сообщение вида «Процедура или функция с указанным именем не определена» либо прямо указывает на обращение к процедуре как к функции — в зависимости от контекста и версии платформы. Разобраться в причине несложно, если понимать, чем процедура отличается от функции и как платформа выполняет проверку модулей.

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

Чем процедура отличается от функции в 1С

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

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

// Процедура — только действия, без результата

Процедура ЗаписатьЛог(ТекстСообщения) Экспорт

ЗаписьЖурналаРегистрации(ТекстСообщения);

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

// Функция — обязательно возвращает значение

Функция ПолучитьКурсВалюты(Валюта, Дата) Экспорт

// ... получение данных

Возврат Курс;

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

Типовые сценарии возникновения ошибки

Присваивание результата переменной

Самый частый случай — разработчик по привычке пишет Результат = МояПроцедура(Параметр);, забыв, что подпрограмма объявлена процедурой. Такое случается при рефакторинге: функцию перевели в процедуру, а все места вызова не исправили. Конфигуратор укажет строку вызова, но настоящая причина — в несоответствии объявления и использования.

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

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

Передача процедуры как аргумента метода

Конструкция Сообщить(ПолучитьОписание());, где ПолучитьОписание — процедура, также вызывает ошибку. Аргумент метода должен быть значением, а процедура его не даёт. Иногда проблема маскируется: процедура находится в общем модуле, и разработчик не видит её объявления в момент написания вызова.

Конфликт имён процедуры и функции

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

Ошибка при проверке модуляУказывает строку вызова

Откройте объявление подпрограммы и посмотрите ключевое слово — Процедура или Функция

Ошибка после рефакторингаПодпрограмму изменили

Найдите все места вызова через поиск по имени и проверьте использование результата

Ошибка при вызове из другого модуляВозможен конфликт имён

Проверьте, нет ли одноимённой процедуры в текущем модуле, перекрывающей функцию общего модуля

Как исправить: два основных пути

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

// Было (ошибка):

Результат = РассчитатьИтог(ТаблицаТоваров);

// Стало (процедура меняет параметр):

Процедура РассчитатьИтог(ТаблицаТоваров, Итог) Экспорт

Итог = ТаблицаТоваров.Итог("Сумма");

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

ИтоговаяСумма = 0;

РассчитатьИтог(ТаблицаТоваров, ИтоговаяСумма);

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

Порядок исправления ошибки
  1. 1
    Дважды щёлкните по сообщению об ошибке в окне служебных сообщений — конфигуратор откроет строку вызова
  2. 2
    Перейдите к объявлению подпрограммы (Ctrl+F12 или поиск по имени) и определите её тип
  3. 3
    Решите: подпрограмма должна возвращать значение или нет
  4. 4
    Если должна — замените Процедура на Функция и добавьте Возврат во все ветки
  5. 5
    Если не должна — уберите присваивание и вызовите процедуру отдельным оператором
  6. 6
    Выполните синтаксический контроль модуля и проверьте остальные места вызова

Как найти все проблемные вызовы

После изменения типа подпрограммы критично проверить все места её использования. В конфигураторе используйте глобальный поиск (Ctrl+Shift+F) по имени подпрограммы с областью поиска «Вся конфигурация». Для каждого найденного вызова проверьте контекст: отдельный это оператор или часть выражения.

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

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

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

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

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

Нет сообщений об ошибках

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

Остались ошибки обращения к процедуре как к функции

Все ветки функции
Норма

Каждый путь выполнения заканчивается оператором Возврат

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

Есть ветка без Возврат — результат будет неопределённым

Поведение в отладчике
Норма

Переменная получает ожидаемое значение и тип

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

Переменная содержит Неопределено или значение другого типа

Типичные ошибки при исправлении

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

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

Типичные ошибки
01
Замена Процедура на Функция без оператора Возврат — вызывающий код получает Неопределено и логика ломается незаметно
02
Исправление одного вызова из многих — остальные места падают в рантайме у пользователей
03
Попытка вернуть значение через параметр с ключевым словом Знач — передаётся копия, изменения теряются
04
Игнорирование конфликта имён с общим модулем — вызов уходит не к той подпрограмме

Когда ошибка не исправляется простой заменой

Если процедура вызывается через механизмы оповещений, длительных операций или Выполнить()/ОценитьВыражение(), статическая проверка может не показать проблему, а ошибка проявится только в рантайме. Динамические вызовы через строковые имена методов требуют ручной проверки соответствия типов подпрограмм.

Отдельный случай — внешние обработки и расширения, где подпрограмма объявлена в одном месте, а используется в переопределяемом коде. Здесь помогает отладчик: поставьте точку останова в месте вызова и посмотрите, какая именно подпрограмма реально выполняется и что она возвращает.

FAQ

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

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

Почему ошибка появилась, хотя код не менялся?

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

Чем отличается Возврат в процедуре от Возврат в функции?

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

Как вернуть из процедуры несколько значений?

Через несколько параметров, переданных по ссылке (без ключевого слова Знач), либо упакуйте результат в структуру и верните её из функции. Второй вариант предпочтительнее: вызов Данные = ПолучитьРеквизиты(Ссылка); читается легче, чем процедура с пятью выходными параметрами.

Ошибка возникает только у пользователя, в конфигураторе проверка чистая. Почему?

Значит, вызов выполняется динамически — через Выполнить(), метод по строковому имени или обработчик оповещения. Статическая проверка такие вызовы не отслеживает. Найдите место динамического вызова и проверьте тип подпрограммы, на которую он ссылается.

Итог

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

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