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

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

Как вернуть значение из процедуры 1С

Разбираем, как вернуть значение из процедуры 1С: замена на функцию, возврат через параметры, глобальные переменные и структуры. Примеры кода и типичные ошибки.

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

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

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

Почему процедура не возвращает значение и чем её заменить

В языке 1С есть чёткое разделение: процедура выполняет действия, функция вычисляет и возвращает результат. Синтаксически вызов процедуры не может стоять в правой части присваивания — конструкция Результат = МояПроцедура(); не скомпилируется.

Самый правильный способ вернуть значение — заменить процедуру функцией. Для этого ключевое слово Процедура меняется на Функция, КонецПроцедуры на КонецФункции, а в нужной точке добавляется оператор Возврат Результат;.

Функция РассчитатьСуммуСНДС(Сумма, СтавкаНДС)

Результат = Сумма + Сумма * СтавкаНДС / 100;

Возврат Результат;

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

Оператор Возврат может встречаться в функции несколько раз — например, в разных ветках условия. Как только выполняется любой из них, работа функции завершается. Если функция завершилась без Возврат Значение;, она вернёт Неопределено, что часто становится источником скрытых ошибок.

Возврат значения через параметр процедуры

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

Процедура ЗаполнитьДанныеКонтрагента(ИНН, ДанныеКонтрагента)

// ... получение данных из регистра или веб-сервиса

ДанныеКонтрагента = Новый Структура("Наименование, Адрес", Наименование, Адрес);

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

// Вызов:

Данные = Неопределено;

ЗаполнитьДанныеКонтрагента("7707083893", Данные);

// Теперь Данные содержит структуру с результатом

Ключевое условие — параметр не должен быть объявлен с ключевым словом Знач. Модификатор Знач означает передачу по значению: внутри процедуры создаётся копия, и все изменения теряются при выходе. Это самая частая причина, почему «параметр не возвращается».

Возврат нескольких значений через структуру

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

Процедура ВыполнитьОбмен(РезультатОбмена)

РезультатОбмена = Новый Структура;

РезультатОбмена.Вставить("Успешно", Истина);

РезультатОбмена.Вставить("ЗагруженоДокументов", 0);

РезультатОбмена.Вставить("ТекстОшибки", "");

// ... логика обмена с заполнением полей

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

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

Возврат через реквизиты объекта и глобальные переменные

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

// В модуле обработки

Перем РезультатВыполнения Экспорт;

Процедура ВыполнитьОбработку() Экспорт

// ... вычисления

РезультатВыполнения = ТаблицаИтогов;

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

Глобальные переменные общих модулей использовать для возврата значений не рекомендуется: это создаёт скрытые зависимости между участками кода, затрудняет отладку и может приводить к ошибкам при повторных вызовах, когда переменная хранит устаревшее значение. Приемлемый вариант — экспортные переменные конкретного объекта обработки с коротким временем жизни.

Типичные ошибки
01
Использование Возврат Значение внутри процедуры — модуль не скомпилируется, так как процедура не может возвращать значение
02
Передача параметра с Знач и ожидание изменений снаружи — изменения теряются при выходе из процедуры
03
Функция без Возврат в одной из веток условия — возвращается Неопределено и ломается логика вызывающего кода
04
Попытка вызвать серверную функцию с клиента без директивы &НаСервере и без серверного вызова — ошибка контекста
05
Хранение результата в глобальной переменной без сброса — при повторном вызове читается устаревшее значение

Возврат значения между клиентом и сервером

В управляемом приложении вызовы между клиентом и сервером имеют ограничения. Серверная функция объявляется с директивой &НаСервере (или &НаСервереБезКонтекста в модуле формы) и возвращает значение обычным оператором Возврат.

&НаСервереБезКонтекста

Функция ПолучитьЦенуНоменклатуры(Номенклатура)

// ... запрос к регистру цен

Возврат Цена;

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

&НаКлиенте

Процедура НоменклатураПриИзменении(Элемент)

Цена = ПолучитьЦенуНоменклатуры(Объект.Номенклатура);

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

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

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

Сравнение способов возврата

Замена на функцию

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

Параметр по ссылке

Когда сигнатуру менять нельзя или нужно вернуть несколько значений. Требует отсутствия Знач в объявлении

Структура-результат

Когда возвращаемых значений много и их состав может расширяться. Нет контроля полей при компиляции

Реквизит объекта или экспортная переменная

Для обработчиков событий форм и обработок, где процедура обязана остаться процедурой

Проверка результата и отладка

После реализации возврата значения обязательно проверьте результат в отладчике. Поставьте точку останова на строке вызова и на операторе Возврат внутри функции, затем посмотрите значение в табло (Shift+F9). Убедитесь, что тип возвращаемого значения соответствует ожиданиям вызывающего кода.

Хорошая практика — защитное программирование: вызывающий код должен проверять результат на Неопределено и на пустые значения, особенно если функция обращается к базе данных или внешним источникам. Конструкция Если Результат = Неопределено Тогда ... КонецЕсли; предотвращает падение с ошибкой «Значение не является значением объектного типа».

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

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

Значение в табло отладчика после вызова
Норма

Ожидаемый тип и содержимое

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

Неопределено или пустое значение без явной причины

Объявление параметра процедуры
Норма

Параметр без Знач, изменения видны снаружи

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

Стоит Знач — изменения теряются

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

Каждая ветка завершается Возврат с осмысленным значением

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

Есть путь выполнения без Возврат

Вызов сервера из клиента
Норма

Директива &НаСервереБезКонтекста, типы сериализуемые

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

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

Что выбрать в вашей ситуации

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

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

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

Как выбрать способ

Код новый или можно менять все места вызоваПерепишите процедуру в функцию с Возврат
Процедура типовая, сигнатуру менять нельзяДобавьте выходной параметр без Знач или используйте расширение
Нужно вернуть несколько разнородных значенийВерните структуру через параметр или из функции
Это обработчик события формыСохраните результат в реквизите формы или объекта
Длительная серверная операция из клиентаФоновое задание с помещением результата во временное хранилище

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

Можно ли написать «Возврат Значение» внутри процедуры?

Нет. В процедуре оператор Возврат допустим только без значения — он просто досрочно завершает выполнение. Конструкция «Возврат Значение;» в процедуре вызовет ошибку при проверке модуля. Для возврата значения преобразуйте процедуру в функцию.

Почему изменения параметра не видны после выхода из процедуры?

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

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

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

Как вернуть таблицу значений с сервера на клиент?

Таблица значений сериализуется и может быть возвращена серверной функцией напрямую в большинстве случаев. Альтернатива — преобразовать её в массив структур или поместить во временное хранилище функцией ПоместитьВоВременноеХранилище и вернуть адрес. Для форм удобно использовать реквизит формы типа ТаблицаЗначений или ДинамическийСписок.

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

Напрямую — нет, процедура фонового задания ничего не возвращает вызывающему коду. Результат помещают во временное хранилище через ПоместитьВоВременноеХранилище(Результат, АдресХранилища), а после завершения задания клиент получает данные функцией ПолучитьИзВременногоХранилища по этому адресу.

Что лучше: много выходных параметров или одна структура?

Структура предпочтительнее при трёх и более возвращаемых значениях: сигнатура остаётся короткой, а добавление нового поля не требует правки всех вызовов. Один-два значения допустимо возвращать отдельными параметрами, если их смысл очевиден из имён.

Итог

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

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