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

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

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

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

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

Частный и очень распространённый случай — метод Удалить(). Многие объекты 1С (элементы справочников, документы, записи регистров, элементы коллекций) имеют метод удаления, который является процедурой. Попытка написать что-то вроде Результат = СправочникОбъект.Удалить(); или Если Элементы.Удалить(Элемент) Тогда приводит именно к этой ошибке.

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

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

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

Когда вы пишете А = МояФункция();, компилятор проверяет: является ли МояФункция функцией. Если это процедура — возникает ошибка «Обращение к процедуре как к функции». Аналогично работает проверка для методов объектов: платформа знает сигнатуру каждого встроенного метода и не позволяет использовать процедурный метод в позиции значения.

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

Типичные сценарии возникновения ошибки с методом Удалить

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

Самый частый случай — попытка проверить, успешно ли прошло удаление, через возвращаемое значение:

Результат = СправочникОбъект.Удалить(); // Ошибка!

Если Результат Тогда

Сообщить("Удалено");

КонецЕсли;

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

Попытка

СправочникОбъект.Удалить();

Сообщить("Объект удалён");

Исключение

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

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

Удаление элемента коллекции в условии

Вторая типичная ситуация — удаление элемента таблицы значений, массива или табличной части внутри условия или цикла с проверкой:

Если ТаблицаЗначений.Удалить(СтрокаТаблицы) Тогда // Ошибка!

...

КонецЕсли;

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

bsl
// Неправильно:
// Если Массив.Удалить(Индекс) Тогда ...

// Правильно:
Если Индекс >= 0 И Индекс < Массив.Количество() Тогда
    Массив.Удалить(Индекс);
КонецЕсли;

Как правильно удалять объекты и элементы коллекций

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

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

Для Инд = 1 - ТабличнаяЧасть.Количество() По 0 Цикл

СтрокаТЧ = ТабличнаяЧасть[-Инд];

Если СтрокаТЧ.Количество = 0 Тогда

ТабличнаяЧасть.Удалить(СтрокаТЧ);

КонецЕсли;

КонецЦикла;

Порядок исправления ошибки
  1. 1
    Найдите строку из сообщения об ошибке — платформа указывает модуль и номер строки
  2. 2
    Определите, какой метод вызывается: посмотрите его описание в синтакс-помощнике (процедура или функция)
  3. 3
    Если метод — процедура, уберите присваивание и вызовите его отдельным оператором
  4. 4
    Если результат нужен, найдите альтернативный метод-функцию (например, НайтиПоНаименованию вместо ручного обхода)
  5. 5
    Проверьте успешность операции через Попытка/Исключение или последующую проверку состояния
  6. 6
    Запустите конфигурацию и убедитесь, что ошибка исчезла, а логика работает как задумано

Другие методы-процедуры, которые часто вызывают как функции

Метод Удалить() — не единственный источник проблемы. Разработчики регулярно ошибаются и с другими методами-процедурами, ожидая от них возвращаемого значения. Ниже перечислены наиболее распространённые.

Метод (процедура)Типичная ошибкаПравильная альтернатива
Объект.Записать()Если Объект.Записать() ТогдаЗаписать() + Попытка/Исключение
Объект.Удалить()Результат = Объект.Удалить()Удалить() + проверка через исключение
Объект.УстановитьПометкуУдаления()Использование в условииВызов отдельным оператором
Коллекция.Очистить()Присваивание результатаВызов, затем проверка Количество() = 0
Сообщить()Возврат Сообщить(Текст)Сообщить отдельно, Возврат отдельно

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

Типичные ошибки
01
Присваивание результата Удалить() переменной — метод ничего не возвращает, компилятор выдаёт ошибку
02
Удаление элементов коллекции в прямом цикле — индексы смещаются, часть элементов пропускается
03
Попытка проверить успех Записать() или Удалить() через Если вместо Попытка/Исключение
04
Копирование кода из другого языка (например, C# или JavaScript), где аналогичные методы возвращают признак успеха
05
Исправление путём замены процедуры на самодельную функцию-обёртку без необходимости — лишний код и путаница

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

Раз метод Удалить() не возвращает признак успеха, возникает резонный вопрос: как узнать, что удаление действительно произошло? Есть три рабочих способа в зависимости от ситуации.

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

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

Третий способ — для массовых удалений использовать пометку удаления вместо непосредственного удаления. Тогда контроль ссылочной целостности выполнит штатная обработка «Удаление помеченных объектов», а вы получите список объектов, которые удалить не удалось, в понятном виде.

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

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

Компиляция модуля
Норма

Модуль сохраняется и проверяется без ошибок

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

Сообщение «Обращение к процедуре как к функции» с указанием строки

Выполнение удаления
Норма

Метод Удалить() выполняется без исключения

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

Срабатывает блок Исключение с текстом ошибки

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

Количество() уменьшилось, элемент не находится

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

Элемент по-прежнему присутствует в коллекции

Состояние объекта в базе
Норма

Повторное получение объекта по ссылке не даёт данных

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

Объект доступен, удаление не выполнено

Когда результат действительно нужен: переделка процедуры в функцию

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

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

// Было:

Процедура УдалитьУстаревшиеЗаписи(Период) Экспорт

...

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

// Стало:

Функция УдалитьУстаревшиеЗаписи(Период) Экспорт

КоличествоУдалённых = 0;

...

Возврат КоличествоУдалённых;

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

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

Маршрут решения

Как выбрать действие

Ошибка на встроенном методе платформы (Удалить, Записать, Очистить)Уберите присваивание, вызывайте метод отдельным оператором, успешность проверяйте через Попытка/Исключение
Ошибка на собственной процедуре, а результат нуженПеределайте процедуру в функцию с оператором Возврат
Ошибка на собственной процедуре, результат не нуженУберите присваивание или использование в выражении — вызовите процедуру отдельной строкой
Нужен признак успеха удаления объекта базы данныхИспользуйте Попытка/Исключение или перейдите на пометку удаления с штатной обработкой удаления помеченных

Профилактика: как не допускать эту ошибку

Основной инструмент профилактики — синтакс-помощник конфигуратора. Перед использованием незнакомого метода откройте его описание (Ctrl+F1 на имени метода) и посмотрите раздел «Возвращаемое значение». Если его нет — метод является процедурой.

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

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

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

Почему метод Удалить() не возвращает признак успеха, как в других языках?

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

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

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

Как удалить элемент массива в цикле, чтобы не пропустить элементы?

Итерируйте массив в обратном порядке — от последнего индекса к первому. Тогда удаление текущего элемента не влияет на индексы ещё не обработанных. Альтернатива — собирать подлежащие удалению элементы в отдельный список и удалять их после основного цикла.

Чем непосредственное удаление объекта отличается от пометки удаления?

Метод Удалить() удаляет объект сразу и вызывает исключение при нарушении ссылочной целостности. УстановитьПометкуУдаления(Истина) только помечает объект; физическое удаление выполняет обработка «Удаление помеченных объектов» с контролем ссылок и возможностью отмены. Для прикладных решений пометка удаления — более безопасный путь.

Ошибка появляется только у части пользователей. Почему?

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

Как быстро найти все места, где процедура вызывается как функция?

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

Итог

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

Процедуры в 1С не возвращают значений, поэтому их нельзя использовать в выражениях. Метод Удалить() — процедура: вызывайте его отдельным оператором, а успешность проверяйте через Попытка/Исключение или последующую проверку состояния. Если результат нужен из собственного кода — переделайте процедуру в функцию. Регулярная проверка конфигурации выявляет такие ошибки до их проявления у пользователей.