Как исправить ошибку «Обращение к процедуре объекта как к функции (Выполнить)» в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Выясняем причину: Процедуры против Функций в 1С

Для начала проанализируем базовый синтаксис встроенного языка 1С. Платформа жестко разграничивает два типа методов:

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

Когда мы пишем код вида Переменная = Объект.Метод();, компилятор 1С ожидает, что Метод() является функцией. Если на самом деле этот метод определен в платформе как процедура, система выдаст ошибку и прекратит выполнение программы.

В чем разница: Запрос против ПостроителяЗапроса

Основная причина путаницы заключается в том, что разработчики привыкают к работе со стандартным объектом Запрос. Давайте сравним поведение метода Выполнить() у двух разных объектов платформы.

Рассмотрим стандартный объект Запрос. У него метод Выполнить() спроектирован как функция. Данный метод возвращает объект типа РезультатЗапроса. Поэтому следующий код абсолютно корректен и используется повсеместно:


// Корректный код для обычного запроса
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура";
РезультатЗапроса = Запрос.Выполнить(); // Здесь Выполнить() работает как ФУНКЦИЯ

Теперь рассмотрим объект ПостроительЗапроса. Этот объект предназначен для динамического конструирования запросов, настройки отборов и порядков. Разработчики платформы спроектировали метод Выполнить() у объекта ПостроительЗапроса (а также у смежного объекта ПостроительОтчета) как процедуру. Она запускает построение запроса, обрабатывает внутренние механизмы и сохраняет полученные данные во внутреннем свойстве Результат самого построителя.

Попытка вызвать его аналогично стандартному запросу неизбежно приведет к ошибке:


// НЕКОРРЕКТНЫЙ КОД - вызовет ошибку компиляции!
РезультатЗапроса = ПостроительЗапроса.Выполнить(); 

Пошаговое решение проблемы

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

Правильный шаблон кода выглядит следующим образом:


// Шаг 1: Инициализируем построитель запроса и задаем текст
ПостроительЗапроса = Новый ПостроительЗапроса;
ПостроительЗапроса.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура";

// Шаг 2: Вызываем процедуру выполнения (без присваивания переменной!)
ПостроительЗапроса.Выполнить();

// Шаг 3: Получаем результат из свойства "Результат" и записываем его в переменную
РезультатЗапроса = ПостроительЗапроса.Результат;

// Шаг 4: Выгружаем данные или обходим выборку
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    // Обработка данных
КонецЦикла;

Именно такое решение позволяет обойти ограничение платформы и корректно получить данные для дальнейшей работы.

Другие популярные методы, вызывающие эту же ошибку

Чтобы закрепить материал, рассмотрим подробнее другие типичные ситуации, в которых разработчики часто совершают аналогичную синтаксическую ошибку:

  1. Установка параметров запроса. Метод УстановитьПараметр() объекта Запрос является процедурой. Код Рез = Запрос.УстановитьПараметр("Склад", Склад); вызовет ошибку. Правильно писать просто: Запрос.УстановитьПараметр("Склад", Склад);.
  2. Чтение текстовых файлов. Методы Прочитать() или Открыть() у объекта ТекстовыйДокумент являются процедурами. Они не возвращают статус успешности операции. Их нужно вызывать как самостоятельные инструкции.
  3. Заполнение коллекций. Метод ЗаполнитьЗначения() у объекта ТаблицаЗначений служит для группового изменения данных в колонке и не возвращает измененную таблицу. Вызов НоваяТаблица = Таблица.ЗаполнитьЗначения(Истина, "Флаг"); приведет к ошибке.
  4. Добавление строк в табличные части на управляемой форме. При работе с интерфейсом метод Элементы.ИмяТаблицы.ДобавитьСтроку() является процедурой (интерфейсным действием). Если вам нужно программно добавить строку в данные и получить ссылку на нее, используйте метод коллекции данных: НоваяСтрока = Объект.ИмяТаблицы.Добавить();.

Архитектурные различия: ПостроительЗапроса против ПостроителяОтчета

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

Современный контекст: почему Построители устарели?

В заключение отметим важный нюанс, касающийся современных стандартов разработки. Семейство объектов класса «Построитель...» активно развивалось в версиях платформы 1С 8.0 и 8.1. В современных конфигурациях на платформе 1С 8.3 (таких как ERP 2, Управление торговлей 11, Бухгалтерия предприятия 3.0) эти технологии признаны устаревшими (legacy).

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

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

← На главную