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

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

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

Разбираем ошибку 1С «Обращение к процедуре объекта как к функции»: причины, примеры кода, способы исправления и типичные ошибки разработчиков.

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

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

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

Что означает эта ошибка и когда она появляется

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

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

Сообщение об ошибке появляется либо в момент сохранения модуля (если включена проверка синтаксиса), либо при первом обращении к коду в режиме предприятия. В толстом клиенте проверка модулей выполняется строже, поэтому ошибка может всплыть там раньше, чем в тонком клиенте.

Как найти источник ошибки в коде

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

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

Обратите внимание на перегруженные сценарии: один и тот же вызов может быть корректным для одного типа объекта и ошибочным для другого. Например, если переменная может содержать либо объект, либо ссылку, набор доступных методов различается, и проверка типа через ТипЗнч() поможет избежать неоднозначности.

Порядок диагностики
  1. 1
    Откройте модуль и строку из сообщения об ошибке
  2. 2
    Найдите вызов метода, результат которого присваивается или используется в выражении
  3. 3
    Перейдите к определению метода (F12) или откройте синтакс-помощник
  4. 4
    Уточните, объявлен ли метод как Процедура или как Функция
  5. 5
    Выберите способ исправления: изменить вызов или изменить объявление метода
  6. 6
    Выполните синтаксическую проверку модуля и повторное тестирование

Способ 1: исправить вызов, убрав присваивание

Если метод действительно не должен ничего возвращать (например, Записать(), Установить(), Показать()), правильное решение — исправить вызывающий код. Уберите присваивание и вызывайте метод как самостоятельный оператор: Объект.Записать(); вместо Результат = Объект.Записать();.

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

Пример корректной обработки записи объекта:

Попытка

Объект.Записать();

Исключение

Сообщить("Ошибка записи: " + ОписаниеОшибки());

КонецПопытки;

Такой подход безопаснее, чем проверка возвращаемого значения, потому что он перехватывает все ошибки, включая ошибки СУБД, нарушение прав доступа и блокировки, которые методом без исключения не контролируются.

Способ 2: изменить объявление метода на функцию

Если метод — ваш собственный (в общем модуле, модуле объекта или формы), и по смыслу он должен возвращать результат, измените объявление. Замените заголовок Процедура ИмяМетода(...) на Функция ИмяМетода(...), добавьте в конце Возврат Результат; и замените завершающее КонецПроцедуры на КонецФункции.

Пример преобразования:

// Было

Процедура ПолучитьОстаток(Номенклатура) Экспорт

// ... расчёт

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

// Стало

Функция ПолучитьОстаток(Номенклатура) Экспорт

// ... расчёт

Возврат Остаток;

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

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

Типичные ситуации с типовыми объектами 1С

Методы записи и чтения объектов

Методы Записать(), Прочитать(), Удалить() у объектов (справочников, документов, регистров) являются процедурами. Попытка написать Если Объект.Записать() Тогда — классическая ошибка. Для контроля результата используйте Попытка/Исключение, а для проверки существования данных — методы поиска, которые действительно возвращают значения.

Методы форм и элементов форм

В управляемых формах многие методы ничего не возвращают: Показать(), Обновить(), УстановитьДоступность(). При этом асинхронные аналоги (ПоказатьВопрос(), ОткрытьФорму()) работают через описание оповещения, и результат приходит в отдельную процедуру-обработчик, а не возвращается из вызова. Попытка получить результат напрямую приведёт либо к этой ошибке, либо к логически неверному коду.

Методы запроса

Метод Выполнить() объекта Запрос — функция, возвращающая результат запроса, а вот УстановитьПараметр() — процедура. Смешение их в одной цепочке вызовов — частый источник ошибки: Выборка = Запрос.УстановитьПараметр("П", 1); не скомпилируется.

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

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

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

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

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

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

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

Проверка конфигурации
Норма

Модуль компилируется без ошибок

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

Ошибка осталась или появилась в другом месте

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

Каждая ветка завершается оператором Возврат

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

Есть ветки без Возврат — вернётся Неопределено

Все вызовы метода
Норма

Вызовы соответствуют новой сигнатуре

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

Найдены вызовы через Выполнить/Вычислить без проверки

Сценарий в режиме предприятия
Норма

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

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

Ошибка времени выполнения или неверное значение

Альтернативные подходы и профилактика

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

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

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

Итог

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

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

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

Можно ли узнать, успешно ли выполнилась процедура, если она ничего не возвращает?

Да, через конструкцию Попытка/Исключение. Если процедура завершилась без исключения — операция прошла. В блоке Исключение доступен текст ошибки через ОписаниеОшибки(). Это стандартный способ контроля методов вроде Записать() и Прочитать().

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

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

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

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

Как исправить ошибку, если вызов идёт через Выполнить() или Вычислить()?

Компилятор не проверяет строки, переданные в Выполнить() и Вычислить(), поэтому ошибка проявится только при выполнении. Найдите такие вызовы глобальным поиском, воспроизведите сценарий в отладчике и приведите строковый код в соответствие с реальной сигнатурой метода.

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

«Не определена» означает, что метода с таким именем не существует в доступной области видимости. «Обращение к процедуре как к функции» означает, что метод существует, но объявлен процедурой, а вызван как функция. В первом случае проверяйте имя и экспортность, во втором — сигнатуру.

Нужно ли менять процедуру на функцию, если результат нужен только в одном месте?

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