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