Разработка и Конфигурация · 11 мин
Как вернуть значение из процедуры 1С
Разбираем, как вернуть значение из процедуры 1С: замена на функцию, возврат через параметры, глобальные переменные и структуры. Примеры кода и типичные ошибки.
Во встроенном языке 1С процедура по определению не возвращает значение — для этого предназначены функции. Однако на практике разработчик часто сталкивается с ситуацией, когда процедура уже написана, вызывается во многих местах, а результат её работы нужно получить снаружи. Существует несколько рабочих приёмов: переписать процедуру в функцию, вернуть значение через параметр, использовать структуру или глобальную переменную.
Выбор способа зависит от контекста: можно ли менять сигнатуру существующего кода, сколько значений нужно вернуть, работаете ли вы в управляемом или обычном приложении, требуется ли передача между клиентом и сервером. Ниже разобраны все основные варианты с примерами кода и указанием ограничений каждого.
Важно понимать, что оператор Возврат внутри процедуры существует, но он лишь прекращает выполнение процедуры без передачи значения. Попытка написать Возврат Значение; в процедуре приведёт к ошибке компиляции модуля.
Почему процедура не возвращает значение и чем её заменить
В языке 1С есть чёткое разделение: процедура выполняет действия, функция вычисляет и возвращает результат. Синтаксически вызов процедуры не может стоять в правой части присваивания — конструкция Результат = МояПроцедура(); не скомпилируется.
Самый правильный способ вернуть значение — заменить процедуру функцией. Для этого ключевое слово Процедура меняется на Функция, КонецПроцедуры на КонецФункции, а в нужной точке добавляется оператор Возврат Результат;.
Функция РассчитатьСуммуСНДС(Сумма, СтавкаНДС)
Результат = Сумма + Сумма * СтавкаНДС / 100;
Возврат Результат;
КонецФункции
Оператор Возврат может встречаться в функции несколько раз — например, в разных ветках условия. Как только выполняется любой из них, работа функции завершается. Если функция завершилась без Возврат Значение;, она вернёт Неопределено, что часто становится источником скрытых ошибок.
Возврат значения через параметр процедуры
Если сигнатуру процедуры менять нельзя (она вызывается из типового кода, обработчиков или внешних компонент), результат можно вернуть через параметр. По умолчанию параметры в 1С передаются по ссылке: изменения, сделанные внутри процедуры, видны вызывающему коду.
Процедура ЗаполнитьДанныеКонтрагента(ИНН, ДанныеКонтрагента)
// ... получение данных из регистра или веб-сервиса
ДанныеКонтрагента = Новый Структура("Наименование, Адрес", Наименование, Адрес);
КонецПроцедуры
// Вызов:
Данные = Неопределено;
ЗаполнитьДанныеКонтрагента("7707083893", Данные);
// Теперь Данные содержит структуру с результатом
Ключевое условие — параметр не должен быть объявлен с ключевым словом Знач. Модификатор Знач означает передачу по значению: внутри процедуры создаётся копия, и все изменения теряются при выходе. Это самая частая причина, почему «параметр не возвращается».
Возврат нескольких значений через структуру
Когда нужно вернуть не одно, а несколько значений (например, признак успеха, текст ошибки и сами данные), удобно упаковать их в структуру. Структура передаётся по ссылке, поэтому её можно заполнять внутри процедуры, добавляя новые ключи.
Процедура ВыполнитьОбмен(РезультатОбмена)
РезультатОбмена = Новый Структура;
РезультатОбмена.Вставить("Успешно", Истина);
РезультатОбмена.Вставить("ЗагруженоДокументов", 0);
РезультатОбмена.Вставить("ТекстОшибки", "");
// ... логика обмена с заполнением полей
КонецПроцедуры
Такой подход хорошо масштабируется: при добавлении нового возвращаемого значения не нужно менять сигнатуру процедуры и все места её вызова — достаточно добавить ключ в структуру. Минус — отсутствие контроля состава полей на этапе компиляции, поэтому состав структуры стоит документировать в комментарии к процедуре.
Возврат через реквизиты объекта и глобальные переменные
В модулях объектов (документов, справочников, обработок) результат можно сохранить в реквизите объекта или экспортной переменной модуля. Вызывающий код затем читает это свойство. Такой приём типичен для внешних обработок, где процедура-обработчик нажатия кнопки не может быть функцией.
// В модуле обработки
Перем РезультатВыполнения Экспорт;
Процедура ВыполнитьОбработку() Экспорт
// ... вычисления
РезультатВыполнения = ТаблицаИтогов;
КонецПроцедуры
Глобальные переменные общих модулей использовать для возврата значений не рекомендуется: это создаёт скрытые зависимости между участками кода, затрудняет отладку и может приводить к ошибкам при повторных вызовах, когда переменная хранит устаревшее значение. Приемлемый вариант — экспортные переменные конкретного объекта обработки с коротким временем жизни.
Возврат значения между клиентом и сервером
В управляемом приложении вызовы между клиентом и сервером имеют ограничения. Серверная функция объявляется с директивой &НаСервере (или &НаСервереБезКонтекста в модуле формы) и возвращает значение обычным оператором Возврат.
&НаСервереБезКонтекста
Функция ПолучитьЦенуНоменклатуры(Номенклатура)
// ... запрос к регистру цен
Возврат Цена;
КонецФункции
&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
Цена = ПолучитьЦенуНоменклатуры(Объект.Номенклатура);
КонецПроцедуры
Ограничения: передавать между клиентом и сервером можно только сериализуемые типы (примитивы, структуры, массивы, ссылки, таблицы значений с ограничениями). Запросы, объекты СКД, COM-объекты и результаты запроса напрямую не передаются — их нужно преобразовать, например результат запроса выгрузить в таблицу значений или массив структур.
Для длительных серверных операций вместо синхронного вызова лучше использовать фоновые задания: процедура в фоновом задании помещает результат во временное хранилище (ПоместитьВоВременноеХранилище), а клиент забирает его по адресу хранилища после завершения.
Сравнение способов возврата
Правильный и предпочтительный способ. Подходит, когда можно менять сигнатуру и все места вызова
Когда сигнатуру менять нельзя или нужно вернуть несколько значений. Требует отсутствия Знач в объявлении
Когда возвращаемых значений много и их состав может расширяться. Нет контроля полей при компиляции
Для обработчиков событий форм и обработок, где процедура обязана остаться процедурой
Проверка результата и отладка
После реализации возврата значения обязательно проверьте результат в отладчике. Поставьте точку останова на строке вызова и на операторе Возврат внутри функции, затем посмотрите значение в табло (Shift+F9). Убедитесь, что тип возвращаемого значения соответствует ожиданиям вызывающего кода.
Хорошая практика — защитное программирование: вызывающий код должен проверять результат на Неопределено и на пустые значения, особенно если функция обращается к базе данных или внешним источникам. Конструкция Если Результат = Неопределено Тогда ... КонецЕсли; предотвращает падение с ошибкой «Значение не является значением объектного типа».
Как проверить результат
Ожидаемый тип и содержимое
Неопределено или пустое значение без явной причины
Параметр без Знач, изменения видны снаружи
Стоит Знач — изменения теряются
Каждая ветка завершается Возврат с осмысленным значением
Есть путь выполнения без Возврат
Директива &НаСервереБезКонтекста, типы сериализуемые
Ошибка вызова или передача несериализуемого типа
Что выбрать в вашей ситуации
Если вы пишете новый код — всегда используйте функцию. Это прозрачно, читаемо и соответствует стандартам разработки 1С. Процедуры оставляйте для действий без результата: записи объекта, вывода сообщения, установки видимости элементов.
Если дорабатываете типовую конфигурацию и не можете менять сигнатуру существующей процедуры — используйте возврат через параметр или расширение конфигурации с аннотацией &ИзменениеИКонтроль, где логику можно обернуть собственной функцией.
Как выбрать способ
Частые вопросы
Можно ли написать «Возврат Значение» внутри процедуры?
Нет. В процедуре оператор Возврат допустим только без значения — он просто досрочно завершает выполнение. Конструкция «Возврат Значение;» в процедуре вызовет ошибку при проверке модуля. Для возврата значения преобразуйте процедуру в функцию.
Почему изменения параметра не видны после выхода из процедуры?
Почти всегда причина в ключевом слове Знач в объявлении параметра — оно включает передачу по значению, и процедура работает с копией. Уберите Знач, чтобы параметр передавался по ссылке. Также проверьте, что вы не переприсваиваете локальную переменную вместо параметра.
Что вернёт функция, если в ней нет оператора Возврат?
Функция вернёт значение Неопределено. Это не вызовет ошибки компиляции, поэтому такой дефект легко пропустить. Проверяйте, что все ветки условий и циклов завершаются явным Возврат с осмысленным значением.
Как вернуть таблицу значений с сервера на клиент?
Таблица значений сериализуется и может быть возвращена серверной функцией напрямую в большинстве случаев. Альтернатива — преобразовать её в массив структур или поместить во временное хранилище функцией ПоместитьВоВременноеХранилище и вернуть адрес. Для форм удобно использовать реквизит формы типа ТаблицаЗначений или ДинамическийСписок.
Можно ли вернуть значение из процедуры фонового задания?
Напрямую — нет, процедура фонового задания ничего не возвращает вызывающему коду. Результат помещают во временное хранилище через ПоместитьВоВременноеХранилище(Результат, АдресХранилища), а после завершения задания клиент получает данные функцией ПолучитьИзВременногоХранилища по этому адресу.
Что лучше: много выходных параметров или одна структура?
Структура предпочтительнее при трёх и более возвращаемых значениях: сигнатура остаётся короткой, а добавление нового поля не требует правки всех вызовов. Один-два значения допустимо возвращать отдельными параметрами, если их смысл очевиден из имён.
Что важно запомнить
Процедура в 1С не возвращает значение — используйте функцию с оператором Возврат. Если сигнатуру менять нельзя, передавайте результат через параметр без Знач, структуру или реквизит объекта. При клиент-серверных вызовах следите за сериализуемостью типов, а для длительных операций применяйте фоновые задания с временным хранилищем.