Возврат значений во встроенном языке 1С: функции, параметры, формы
Содержание
Чтобы вернуть значение в 1С, объявите метод как Функция … КонецФункции и напишите внутри Возврат Значение;. Вызывающий код получит результат через присваивание: Сумма = ПосчитатьСумму(Документ);. Процедура значение вернуть не может: в ней Возврат без выражения только досрочно завершает работу.
Второй способ — изменить параметр, переданный без Знач: изменения увидит вызывающий код. Если нужно вернуть несколько значений, собирают Структуру или Массив. Ниже разобраны все варианты для платформы 8.3, включая управляемые формы, серверные вызовы и асинхронный код.
Как работает оператор Возврат в функции
Синтаксис короткий:
Функция ПроцентСкидки(СуммаЗаказа)
Если СуммаЗаказа >= 100000 Тогда
Возврат 10;
ИначеЕсли СуммаЗаказа >= 50000 Тогда
Возврат 5;
КонецЕсли;
Возврат 0;
КонецФункции
Вызов: Скидка = ПроцентСкидки(72000); — в переменную Скидка попадёт 5.
Что нужно знать про Возврат:
- ⏹️ Выполнение прекращается сразу. Код после сработавшего
Возвратне выполняется, даже если он внутри цикла или условия. - 🔁 Операторов может быть несколько. Удобно выходить из функции рано, как в примере выше, вместо вложенных
Если. - ❓ Без
Возвратфункция вернётНеопределено. Ошибки не будет. Это частая причина «пустых» результатов, когда одна из веток условия забыла вернуть значение. - 🧮 После
Возвратможно писать выражение.Возврат Цена * Количество;или тернарный оператор:Возврат ?(Остаток > 0, Остаток, 0);. - 🧱 Тип не объявляется. Встроенный язык динамический: одна функция может вернуть число в одной ветке и строку в другой. Технически это работает, но читать такой код тяжело. Держите один тип результата (или
Неопределенокак признак «нет данных»).
Если функция ничего не нашла, возвращайте Неопределено или пустую ссылку соответствующего типа и опишите это в комментарии над методом. Вызывающий код тогда проверяет Если Результат = Неопределено Тогда, а не гадает.
Возврат внутри Попытка и циклов
Возврат разрешён внутри Попытка … Исключение … КонецПопытки и внутри любых циклов. Выход из цикла через Возврат завершает всю функцию, а не только цикл. Если нужно выйти только из цикла, используйте Прервать.
Функция НайтиСтрокуПоАртикулу(Таблица, Артикул)
Для Каждого Строка Из Таблица Цикл
Если Строка.Артикул = Артикул Тогда
Возврат Строка;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Функция и процедура: в чём разница при возврате
| Признак | Функция | Процедура |
|---|---|---|
| Ключевые слова | Функция … КонецФункции | Процедура … КонецПроцедуры |
Возврат Значение; | да | нет, синтаксическая ошибка |
Возврат; без значения | вернёт Неопределено | досрочный выход |
Вызов в выражении А = Метод() | да | нет, ошибка при проверке модуля |
Вызов отдельной строкой Метод(); | да, результат отбрасывается | да |
| Типичное применение | вычислить, найти, проверить | записать, заполнить, изменить |
Правило выбора простое. Метод что-то считает или ищет — делайте функцию. Метод что-то меняет (записывает документ, заполняет табличную часть) — процедуру.
Пограничный случай — метод меняет данные и сообщает, удалось ли. Здесь удобна функция, которая возвращает Истина/Ложь:
Функция ЗаписатьБезопасно(Объект)
Попытка
Объект.Записать();
Исключение
ЗаписьЖурналаРегистрации("Запись объекта",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
Чтобы функция была доступна из других модулей (например, из общего модуля), после списка параметров добавьте Экспорт: Функция ПроцентСкидки(СуммаЗаказа) Экспорт.
Возврат через параметры: Знач и передача по ссылке
По умолчанию параметры в 1С передаются по ссылке. Если метод присвоит параметру новое значение, переменная в вызывающем коде тоже изменится. Так из процедуры можно вернуть результат, а из функции — дополнительный результат помимо основного.
Функция РазобратьФИО(ФИО, Фамилия, Имя)
Части = СтрРазделить(СокрЛП(ФИО), " ", Ложь);
Если Части.Количество() < 2 Тогда
Возврат Ложь;
КонецЕсли;
Фамилия = Части[0];
Имя = Части[1];
Возврат Истина;
КонецФункции
// Вызов
Фамилия = "";
Имя = "";
Если РазобратьФИО("Петрова Анна Сергеевна", Фамилия, Имя) Тогда
Сообщить(Фамилия + ", " + Имя); // Петрова, Анна
КонецЕсли;
Такие параметры называют выходными. Отдельного ключевого слова для них в языке нет: выходным параметр делает сам факт присваивания внутри метода.
Когда ставить Знач
Модификатор Знач перед именем параметра передаёт копию значения. Присваивание внутри метода тогда не затронет переменную снаружи.
Функция Нормализовать(Знач Текст)
Текст = НРег(СокрЛП(Текст)); // исходная переменная не изменится
Возврат Текст;
КонецФункции
С коллекциями Знач не защищает содержимое. Для массива, структуры или таблицы значений копируется только ссылка на объект. Если внутри метода вызвать Массив.Добавить() или Структура.Вставить(), изменится исходная коллекция. Защищает Знач только от присваивания всей переменной нового объекта.
| Что делаете внутри метода | Без Знач | С Знач |
|---|---|---|
Параметр = 5; (присваивание) | меняется снаружи | не меняется |
Массив.Добавить(1); | меняется снаружи | тоже меняется |
Массив = Новый Массив; | снаружи новый массив | снаружи старый массив |
Если метод не должен портить переданную коллекцию, сделайте копию внутри: для таблицы значений — Копия = Таблица.Скопировать();, для массива — новый массив с перебором элементов.
Значения по умолчанию задаются через =: Функция Остаток(Номенклатура, Дата = Неопределено). Параметры со значением по умолчанию можно пропускать при вызове.
Как вернуть несколько значений: структура, массив, таблица
Возврат принимает одно выражение. Чтобы отдать несколько результатов, упакуйте их в коллекцию.
Структура — для разнородных результатов
Самый читаемый вариант: у каждого значения есть имя.
Функция ИтогиЗаказа(Заказ)
Результат = Новый Структура;
Результат.Вставить("Сумма", 0);
Результат.Вставить("СуммаНДС", 0);
Результат.Вставить("КоличествоСтрок", Заказ.Товары.Количество());
Для Каждого Строка Из Заказ.Товары Цикл
Результат.Сумма = Результат.Сумма + Строка.Сумма;
Результат.СуммаНДС = Результат.СуммаНДС + Строка.СуммаНДС;
КонецЦикла;
Возврат Результат;
КонецФункции
// Вызов
Итоги = ИтогиЗаказа(ЗаказОбъект);
Сообщить("Сумма: " + Формат(Итоги.Сумма, "ЧДЦ=2"));
Структуру можно создать одной строкой: Новый Структура("Сумма, СуммаНДС", 0, 0).
Какую коллекцию выбрать
| Коллекция | Когда возвращать | Доступна на клиенте |
|---|---|---|
Структура | несколько именованных значений | да |
ФиксированнаяСтруктура | то же, но нельзя менять | да |
Массив | список однотипных значений (ссылки, числа) | да |
Соответствие | пары «ключ → значение», поиск по ключу | да |
ТаблицаЗначений | строки с колонками, результат запроса | нет, только сервер |
СписокЗначений | значения с представлениями, выбор из списка | да |
Результат запроса удобно возвращать сразу таблицей: Возврат Запрос.Выполнить().Выгрузить();. Если нужна только одна колонка ссылок — Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");, получится массив.
Повторное использование возвращаемых значений
У общего модуля есть свойство «Повторное использование возвращаемых значений»: «На время вызова» или «На время сеанса». Платформа кэширует результат экспортных функций такого модуля по набору параметров.
- ✅ Подходит для редко меняющихся данных: настройки, константы, списки видов.
- ⚠️ Возвращайте из таких функций
ФиксированныйМассивиФиксированнуюСтруктуру. Обычную коллекцию вызывающий код может изменить, и следующий вызов получит из кэша уже испорченные данные.
Возврат значений между клиентом и сервером в управляемой форме
В управляемой форме код делится директивами компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста. Вызов серверной функции с клиента — это передача данных по сети, и здесь свои ограничения.
Что можно вернуть с сервера на клиент
Возвращать можно только значения, которые существуют на клиенте: примитивные типы, ссылки, Структура, Массив, Соответствие, СписокЗначений, фиксированные коллекции.
Нельзя вернуть на клиент ТаблицаЗначений, Запрос, объект справочника или документа (СправочникОбъект, ДокументОбъект). Платформа выдаст ошибку при вызове. Обходные пути:
- 📦 Преобразовать таблицу в массив структур на сервере и вернуть массив.
- 🗂️ Загрузить таблицу в реквизит формы типа
ТаблицаЗначенийчерезЗначениеВРеквизитФормы— на клиент он придёт как данные формы. - 🏷️ Вернуть ссылку, а нужные реквизиты дочитать отдельным серверным вызовом.
&НаКлиенте
Процедура ПоказатьОстаток(Команда)
Остаток = ОстатокНаСервере(Объект.Номенклатура, Объект.Склад);
Сообщить("Остаток: " + Формат(Остаток, "ЧГ=0"));
КонецПроцедуры
&НаСервереБезКонтекста
Функция ОстатокНаСервере(Знач Номенклатура, Знач Склад)
// запрос к регистру остатков
Возврат 0;
КонецФункции
Почему на сервере стоит писать Знач
При серверном вызове параметры без Знач после выполнения передаются обратно на клиент. Для больших структур и массивов это лишний трафик. Если серверная функция не меняет параметры, объявляйте их с Знач.
&НаСервереБезКонтекста не передаёт данные формы на сервер. Такой вызов быстрее, но результат вы получите только через Возврат или выходные параметры: реквизиты формы оттуда недоступны.
Большие объёмы: временное хранилище
Файлы, отчёты, результаты фонового задания возвращают через временное хранилище. Сервер кладёт данные ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор) и возвращает адрес строкой. Клиент забирает ПолучитьИзВременногоХранилища(Адрес).
Как вернуть результат из формы и асинхронного вызова
Немодальные окна и диалоги не останавливают код, поэтому привычное Результат = ОткрытьФормуМодально(…) в веб-клиенте и при отключённой модальности не работает
. Значение приходит позже.
Возврат из формы через Закрыть
Открываемая форма завершает работу командой Закрыть(Результат);. Вызывающая форма получает это значение в процедуре-обработчике, переданной в ОписаниеОповещения:
&НаКлиенте
Процедура ВыбратьПериод(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВыбораПериода", ЭтотОбъект);
ОткрытьФорму("Обработка.Помощник.Форма.ВыборПериода", , ЭтаФорма, , , ,
Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораПериода(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат; // пользователь закрыл окно без выбора
КонецЕсли;
Объект.НачалоПериода = Результат.Начало;
КонецПроцедуры
Обработчик оповещения обязательно экспортный. Если пользователь закрыл форму крестиком, придёт Неопределено.
Для форм выбора есть второй путь: форма вызывает ОповеститьОВыборе(Значение), а владелец обрабатывает событие ОбработкаВыбора.
Асинх и Ждать
С платформы 8.3.18 есть ключевые слова Асинх и Ждать. Асинхронная функция возвращает Обещание, а Ждать достаёт из него результат:
&НаКлиенте
Асинх Процедура УдалитьСтроки(Команда)
Ответ = Ждать ВопросАсинх("Удалить выбранные строки?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
УдалитьНаСервере();
КонецЕсли;
КонецПроцедуры
Возврат Значение; внутри Асинх Функция упаковывает значение в обещание. Вызывающий код получит его только через Ждать; без Ждать в переменную попадёт само Обещание.
Возврат. Несколько значений — структура.Возврат типа, доступного на клиенте. Таблицу значений — массивом структур. Параметры с Знач.Закрыть(Результат) в форме и обработчик ОписаниеОповещения у владельца, либо Ждать в асинхронной процедуре.Отладка: как проверить, что вернула функция
Когда функция возвращает не то, проще всего посмотреть значение в отладчике конфигуратора.
- Откройте модуль и поставьте точку останова на строке с
ВозвратклавишейF9. - Запустите отладку
F5и выполните действие, которое вызывает функцию. - Наведите курсор на переменную или выделите выражение после
Возврати нажмитеShift+F9— откроется окно вычисления выражения. Для коллекций там видно содержимое по строкам и полям. - Чтобы пройти внутрь вызываемой функции, используйте
F11, чтобы перешагнуть вызов —F10, чтобы выйти из текущей функции к вызывающему коду —Shift+F11. - Вернувшись в вызывающий код, проверьте переменную, в которую записался результат.
Если веток с Возврат несколько, ставьте точки на каждой: сразу видно, по какой ветке пошло выполнение. Точка на строке КонецФункции срабатывает, когда ни один Возврат не выполнился, — значит, функция вернёт Неопределено.
Серверный код в клиент-серверной базе отлаживается, только если на сервере 1С включена отладка. Её включает администратор сервера; на рабочем сервере без согласования этого не делайте: отладчик останавливает выполнение кода у пользователей, попавших на точку останова.
Без отладчика результат можно вывести через Сообщить(…) на клиенте или записать в журнал регистрации ЗаписьЖурналаРегистрации(…) на сервере. Перед выводом коллекции преобразуйте в строку: например, для структуры перебором Для Каждого КлючИЗначение Из Структура Цикл.
Частые ошибки при возврате значений
- ❌ Ветка без
Возврат. Функция «иногда» возвращаетНеопределено, а дальше падает обращение к полю:Итоги.Сумма. ДобавьтеВозвратв конец функции на случай, когда ни одно условие не сработало. - ❌ Изменили коллекцию-параметр, рассчитывая на
Знач.Значкопирует ссылку, а не содержимое. Делайте явную копию. - ❌ Вернули
ТаблицаЗначенийв клиентский код. Таблица существует только на сервере. Возвращайте массив структур или пишите в реквизит формы. - ❌ Склеили число со строкой.
"Сумма: " + 1500даст строку с представлением числа в формате пользователя, иногда с пробелом-разделителем разрядов. Для стабильного вывода используйтеФормат(Число, "ЧГ=0")илиСтрШаблон("Сумма: %1", Число). - ❌ Ждут результат от немодальной формы сразу после
ОткрытьФорму. Код после открытия выполнится до того, как пользователь что-то выберет. Результат обрабатывайте только в обработчике оповещения. - ❌ Меняют то, что вернула функция с повторным использованием. Данные из кэша изменятся для всех следующих вызовов в сеансе. Возвращайте фиксированные коллекции.
Частые вопросы
Можно ли вернуть значение из процедуры?
Возврат — нет. Можно изменить параметр, переданный без Знач, или переделать процедуру в функцию: вызов отдельной строкой продолжит работать.Что вернёт функция, если в ней нет оператора Возврат?
Неопределено. Ошибки выполнения не будет, поэтому такие места ищут отладчиком или проверкой результата на Неопределено.Как вернуть из функции сразу два числа?
Возврат Новый Структура("Минимум, Максимум", Мин, Макс);. Второй вариант — выходные параметры без Знач.Можно ли вернуть из функции саму функцию или ссылку на метод?
ОписаниеОповещения или вызывают метод общего модуля по условию.Чем Возврат отличается от ВызватьИсключение?
Возврат штатно завершает метод с результатом. ВызватьИсключение прерывает выполнение с ошибкой, и её нужно перехватить в Попытка выше по стеку, иначе пользователь увидит сообщение об ошибке.