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