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