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