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