Разработка и Конфигурация · 12 мин
Как вернуть значение в 1С: функции, процедуры и параметры
Как вернуть значение в 1С из функции и процедуры: оператор Возврат, параметры по ссылке, возврат структур и массивов, типичные ошибки разработчика.
Возврат значения — базовый приём встроенного языка 1С, без которого невозможно построить переиспользуемый код. Функция вычисляет результат и передаёт его вызывающему коду через оператор Возврат, процедура может изменять переданные ей параметры, а сложные данные удобно возвращать в виде структур, массивов или таблиц значений.
Ошибки при возврате значений — одна из частых причин дефектов в доработках типовых конфигураций: функция «молча» возвращает Неопределено, параметр изменяется там, где этого не ожидали, а результат запроса теряется из-за неправильной передачи между сервером и клиентом. Ниже разобраны рабочие способы вернуть значение в разных сценариях, ограничения платформы и признаки, по которым можно проверить корректность кода.
Как вернуть значение из функции оператором Возврат
Функция — единственный вид метода во встроенном языке 1С, который возвращает значение напрямую. Объявление начинается со слова Функция, а результат передаётся оператором Возврат с указанием выражения. После выполнения оператора работа функции немедленно прекращается.
Функция ЦенаСНДС(Цена, СтавкаНДС) Экспорт
Если Цена <= 0 Тогда
Возврат 0;
КонецЕсли;
Возврат Цена + Цена * СтавкаНДС / 100;
КонецФункции
Вызов выглядит как присваивание: Итог = ЦенаСНДС(1000, 20);. Если функция завершилась без оператора Возврат (например, ни одна ветка условия не сработала), она вернёт значение Неопределено. Это частый источник скрытых ошибок: код не падает, но дальше по цепочке расчёт даёт неверный результат.
Правило надёжного кода — каждая ветка логики должна заканчиваться осмысленным возвратом. Перед завершением функции полезно проверить себя: что вернётся при пустых входных данных, при отрицательных числах, при незаполненной ссылке.
Как получить результат из процедуры через параметры
Процедура не имеет оператора возврата значения: Возврат; в процедуре только прерывает её выполнение. Тем не менее «вернуть» данные из процедуры можно, потому что параметры по умолчанию передаются по ссылке — изменения внутри процедуры видны снаружи.
Процедура РазобратьСтроку(СтрокаДанных, Артикул, Количество) Экспорт
Части = СтрРазделить(СтрокаДанных, ";");
Артикул = Части[0];
Количество = Число(Части[1]);
КонецПроцедуры
// Вызов:
Арт = ""; Кол = 0;
РазобратьСтроку("A-100;5", Арт, Кол);
// Арт = "A-100", Кол = 5
Если перед параметром указать слово Знач, в процедуру попадёт копия, и изменения не выйдут наружу. Это защищает исходные данные, но делает невозможным возврат результата через такой параметр. Осознанно ставьте Знач только там, где побочное изменение недопустимо.
Когда процедура должна вернуть больше одного значения, читаемость кода резко падает: вызывающая сторона вынуждена заранее объявлять переменные-заготовки. В таких случаях чаще правильнее преобразовать процедуру в функцию, возвращающую структуру.
Функция или процедура с параметрами
Подходит, когда нужен один результат. Код вызова компактный, результат можно использовать прямо в выражении.
Подходит, когда метод по смыслу выполняет действие, а изменение переменных — побочный эффект. При 2–3 и более возвращаемых значениях код становится трудночитаемым.
Оптимально для нескольких результатов: вызывающий код получает именованные поля, а не позиционные параметры.
Как вернуть несколько значений: структура, массив, таблица
Когда результат состоит из нескольких связанных данных, их упаковывают в составной объект. Самый удобный вариант — структура с именованными ключами: вызывающий код обращается к полям по имени и не зависит от порядка.
Функция ОстаткиПоТовару(Номенклатура) Экспорт
Результат = Новый Структура;
Результат.Вставить("СвободныйОстаток", 0);
Результат.Вставить("ВРезерве", 0);
Результат.Вставить("Найден", Ложь);
// ... запрос к регистру накопления ...
Возврат Результат;
КонецФункции
Массив подходит для однотипного списка — например, набора найденных ссылок. Таблицу значений возвращают, когда результат представляет собой выборку с колонками: её удобно обходить в цикле, сортировать и сворачивать. Для передачи таблицы между сервером и клиентом в управляемых формах используют реквизит формы типа «ТаблицаЗначений» или временное хранилище.
Избегайте возврата «сырого» результата запроса (РезультатЗапроса) наружу из общих модулей: вызывающий код получает лишнюю зависимость от структуры запроса. Лучше сразу выгрузить выборку в таблицу значений методом Выгрузить().
- 1Определите состав результата: одно значение, список или таблица с колонками
- 2Объявите структуру, массив или таблицу значений в начале функции
- 3Заполните объект данными, обработав случай пустого результата
- 4Верните объект оператором Возврат
- 5В вызывающем коде проверьте заполненность перед использованием
Возврат значения в управляемых формах и между клиентом и сервером
В управляемом приложении код делится на клиентский и серверный, и это накладывает ограничения на возвращаемые данные. Функция с директивой &НаСервере может вернуть клиенту только сериализуемые типы: примитивы, структуры, массивы, ссылки, а также специально предназначенные объекты вроде ДанныеФормыСтруктура. Вернуть, например, объект Запрос или COMОбъект с сервера на клиент нельзя — платформа выдаст ошибку передачи данных.
Диалоговые формы возвращают значение через метод Закрыть(ПараметрЗакрытия). Вызывающая сторона получает его либо через описание оповещения в ОткрытьФорму с обработчиком, либо из свойства формы после модального открытия. Типичный сценарий — форма подбора, которая возвращает структуру с выбранными товарами.
// В форме выбора:
Закрыть(Новый Структура("Товар, Количество", ВыбранныйТовар, 1));
// В вызывающей форме:
Процедура ОбработатьВыбор(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = Результат.Товар;
КонецЕсли;
КонецПроцедуры
Возврат значения из запроса и типовых механизмов
Частая практическая задача — вернуть значение, полученное запросом: остаток, цену, признак наличия документа. Надёжный шаблон — выполнить запрос, проверить, что выборка не пуста, и вернуть значение либо значение по умолчанию.
Функция ЕстьДокументыПоКонтрагенту(Контрагент) Экспорт
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1 Реализация.Ссылка
|ИЗ Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ Реализация.Контрагент = &Контрагент");
Запрос.УстановитьПараметр("Контрагент", Контрагент);
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции
Обратите внимание на приём с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1: когда нужен только факт существования, не требуется выбирать все записи. Это заметно быстрее на больших таблицах и не нагружает память выборкой, которая всё равно не будет использована.
Для значений по умолчанию используйте явную ветку: если выборка пустая — вернуть 0, пустую строку или пустую ссылку нужного типа. Возврат «правильной пустоты» избавляет вызывающий код от проверок на Неопределено.
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Цена;
Иначе
Возврат 0;
КонецЕсли;Типичные ошибки при возврате значений
Самая распространённая ошибка — «проваливающийся» возврат: функция содержит Возврат только внутри условия, а при ложном условии завершается молча. Второе место занимает несогласованность типов: одна ветка возвращает число, другая — строку, третья — Неопределено. Такой код работает «почти всегда» и ломается на граничных данных.
Отдельная группа ошибок связана с параметрами. Разработчик ожидает, что процедура изменит переменную, но параметр объявлен с Знач — изменение теряется. Обратная ситуация: функция неожиданно портит переданный ей объект, потому что параметр без Знач изменили внутри. Оба случая диагностируются поиском по тексту модуля и проверкой сигнатуры метода.
В клиент-серверном коде типичная ошибка — попытка вернуть несериализуемый объект с сервера или обратиться к результату функции &НаСервереБезКонтекста как к объекту формы. Также нельзя забывать, что в общих модулях с признаком «Сервер» функция недоступна на клиенте: вызов приведёт к ошибке компиляции в тонком клиенте.
Как проверить, что функция возвращает правильное значение
Простейшая проверка — отладчик: точка останова на операторе Возврат показывает фактическое значение и его тип в табло. Если функция вызывается из многих мест, полезно поставить точку останова на первой строке функции и пройти по шагам, отслеживая, какая ветка сработала.
Для прикладных проверок без отладчика временно выводите результат через Сообщить() или запись в журнал регистрации, но обязательно убирайте такой код перед передачей доработки в рабочую базу. В крупных внедрениях критичные функции покрывают тестами: готовятся входные данные, результат сравнивается с ожидаемым, включая граничные случаи — пустые параметры, нулевые суммы, незаполненные ссылки.
Признак зрелого кода — функция ведёт себя предсказуемо на любых входных данных: либо возвращает осмысленное значение согласованного типа, либо явно вызывает исключение с понятным текстом, если продолжать работу нельзя.
Как проверить результат
Тип и содержимое соответствуют ожиданию во всех сценариях
Неопределено или тип меняется от вызова к вызову
Возвращается значение по умолчанию того же типа
Ошибка выполнения или молчаливый Неопределено
Изменяются только те параметры, которые задуманы как выходные
Исходные данные вызывающего кода портятся неожиданно
Что важно запомнить
Функция возвращает значение оператором Возврат, процедура — через параметры по ссылке. Несколько результатов упаковывайте в структуру. Обеспечьте возврат в каждой ветке и единый тип результата. Между клиентом и сервером передавайте только сериализуемые данные.
Частые вопросы
Что вернёт функция, если в ней нет оператора Возврат?
Функция вернёт значение Неопределено. Синтаксис-проверка конфигуратора на это не ругается, поэтому дефект обнаруживается только в рантайме. Чтобы избежать таких ситуаций, добавляйте в конец функции возврат значения по умолчанию, даже если все основные ветки уже содержат Возврат.
Можно ли прервать процедуру досрочно?
Да, оператор Возврат; без выражения завершает процедуру немедленно. Это удобно для раннего выхода при невыполненных условиях: сначала проверяются предусловия, затем идёт основная логика без глубокой вложенности «Если».
Как вернуть из функции таблицу значений на клиент в управляемой форме?
Напрямую таблицу значений с сервера на клиент передать нельзя. Рабочие варианты: преобразовать таблицу в массив структур, поместить её во временное хранилище и вернуть адрес, либо загрузить данные в реквизит формы типа «ТаблицаЗначений» в серверной процедуре формы.
Чем структура лучше нескольких выходных параметров процедуры?
Поля структуры имеют имена, поэтому вызывающий код читается без заглядывания в сигнатуру метода, а порядок полей не имеет значения. Кроме того, состав результата легко расширить новым ключом, не меняя все места вызова, — для позиционных параметров это невозможно.
Как вернуть значение из формы, открытой через ОткрытьФорму?
В закрываемой форме вызовите Закрыть(Результат), передав нужное значение. В вызывающем коде при открытии укажите описание оповещения — процедуру, которая получит результат первым параметром. Если форма открыта модально через ОткрытьФормуМодально, результат возвращается как значение этого метода.
Можно ли из функции вернуть ссылку на ещё не записанный объект?
Нет, пока объект не записан методом Записать(), его ссылка пустая. Правильный порядок: заполнить объект, записать его, затем вернуть Объект.Ссылка. Если запись может завершиться ошибкой (например, из-за проверки заполнения), оборачивайте её в попытку и возвращайте пустую ссылку при неудаче.