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