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