К статье
Практический материал

Разработка и Конфигурация · 12 мин

Функции в 1С 8.3: как устроены и как с ними работать

Разбор функций в 1С 8.3: синтаксис, параметры, возврат значения, отличие от процедур, экспортные функции, типичные ошибки и примеры кода.

Функция — один из базовых строительных блоков встроенного языка 1С:Предприятие 8.3. Она объединяет набор операторов в именованный блок, который можно вызывать многократно из разных мест кода, передавая входные данные и получая результат. Понимание того, как функции объявляются, как передаются параметры и как возвращается значение, необходимо любому разработчику и внедренцу, который дорабатывает конфигурацию или пишет собственные обработчики.

Главное отличие функции от процедуры — обязательный возврат значения через оператор Возврат. Если процедура просто выполняет действия (записывает документ, выводит сообщение), то функция вычисляет и отдаёт результат: сумму скидки, признак проверки, найденную ссылку на элемент справочника. Возвращаемое значение можно присвоить переменной, использовать в условии или передать дальше в другую функцию.

Функции размещаются в модулях: модуле объекта, модуле формы, общем модуле, модуле менеджера. От места размещения зависит видимость функции, доступный контекст и возможность вызова с клиента или с сервера. Неправильный выбор модуля — одна из самых частых причин ошибок «Процедура или функция с указанным именем не определена».

Как объявляется функция: синтаксис и структура

Объявление функции начинается с ключевого слова Функция, за которым следуют имя и список параметров в круглых скобках. Завершается блок оператором КонецФункции. Имя должно быть уникальным в пределах модуля и не может совпадать с именами встроенных методов платформы в том же контексте.

Функция РассчитатьСуммуСНДС(СуммаБезНДС, СтавкаНДС = 20) Экспорт

СуммаНДС = СуммаБезНДС * СтавкаНДС / 100;

Возврат СуммаБезНДС + СуммаНДС;

КонецФункции

Ключевое слово Экспорт делает функцию доступной из других модулей. Без него функция считается приватной: её можно вызывать только внутри того же модуля. В общих модулях функции без Экспорт использовать извне невозможно — это удобно для вспомогательных вычислений, которые не должны «торчать» наружу.

Параметр может иметь значение по умолчанию, как СтавкаНДС = 20 в примере. Такие параметры указываются в конце списка и могут быть опущены при вызове. Если параметр без значения по умолчанию не передан, платформа выдаст ошибку «Недостаточно фактических параметров».

Как передаются параметры: по значению и по ссылке

По умолчанию параметры передаются по ссылке: если внутри функции изменить значение параметра, изменится и переменная в вызывающем коде. Чтобы запретить изменение, перед именем параметра ставится ключевое слово Знач — тогда в функцию передаётся копия значения.

Функция ДобавитьСтроку(Знач ИсходныйТекст, Добавка)

ИсходныйТекст = ИсходныйТекст + Добавка; // изменится только копия

Возврат ИсходныйТекст;

КонецФункции

На практике передача по ссылке для примитивных типов (число, строка, дата) редко используется намеренно и чаще становится источником трудноуловимых ошибок: функция «молча» меняет переменную вызывающего кода. Хороший тон — либо всегда использовать Знач для входных данных, либо явно документировать, что параметр является одновременно выходным.

Объекты вроде таблиц значений, структур и массивов ведут себя иначе: они и так передаются как ссылки на объект, поэтому изменение содержимого коллекции внутри функции отразится на оригинале даже с ключевым словом Знач — Знач защищает только саму переменную, а не данные, на которые она указывает.

Возврат значения и особенности оператора Возврат

Оператор Возврат немедленно прекращает выполнение функции и передаёт указанное значение вызывающему коду. Код, написанный после Возврат в той же ветке, выполняться не будет — компилятор 1С выдаёт предупреждение о недостижимом коде, если он стоит безусловно.

Если функция завершилась без явного оператора Возврат со значением, она вернёт Неопределено. Это частая причина логических ошибок: разработчик забыл Возврат в одной из веток условия, и вызывающий код получает Неопределено вместо числа или ссылки. Перед завершением функции полезно проверять, что каждая ветвь логики заканчивается возвратом осмысленного значения.

Тип возвращаемого значения в 1С не фиксируется при объявлении: одна и та же функция может в разных ситуациях вернуть число, строку или Неопределено. Это гибкость, но и риск. Практическое правило — возвращать значения одного типа, а для признака «результат не найден» использовать единое соглашение, например Неопределено или пустую ссылку, и описывать его в комментарии к функции.

Директивы компиляции и контекст выполнения

Перед объявлением функции в модуле формы или общем модуле указывается директива компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста. Директива определяет, где будет скомпилирован и выполнен код, и какие объекты в нём доступны.

Функции &НаСервереБезКонтекста не имеют доступа к данным формы — все нужные значения передаются параметрами. Это самый производительный вариант серверного вызова из формы, потому что платформе не нужно сериализовать весь контекст формы для передачи на сервер. Если функция только считает по переданным данным — выбирайте именно этот вариант.

Вызов серверной функции с клиента — это сетевое обращение, которое стоит ресурсов и времени. Частые серверные вызовы в цикле (например, получение цены для каждой строки таблицы по отдельности) — классическая причина «тормозов» управляемых форм. Правильный подход: собрать данные на клиенте в массив и передать в одну серверную функцию, которая обработает всё пакетом.

Где размещать функции: выбор модуля

Модуль объекта подходит для функций, работающих с данными конкретного объекта: проверка заполнения реквизитов, расчёты по табличной части документа. Модуль формы — для логики интерфейса: обработчики команд, пересчёт итогов на форме, управление видимостью элементов.

Общие модули — место для функций, которые нужны в разных объектах конфигурации: расчёт налогов, работа со строками, формирование представлений. Для них настраиваются свойства: «Сервер», «Клиент (управляемое приложение)», «Вызов сервера», «Привилегированный режим». Функция в общем модуле без включённого флага «Вызов сервера» недоступна с клиента.

Привилегированный режим общего модуля отключает проверку прав доступа к данным. Это удобно для служебных операций, но опасно: пользователь с ограниченными правами сможет косвенно прочитать или изменить данные, к которым у него нет доступа. Включайте привилегированный режим осознанно и не выносите в такой модуль функции, принимающие произвольные запросы или имена объектов параметрами.

Сравнение вариантов размещения

Модуль объекта

Логика конкретного объекта: расчёты по его реквизитам и табличным частям. Не подходит для кода, нужного другим объектам.

Модуль формы

Интерфейсная логика и обработчики событий формы. Серверные функции здесь доступны только внутри этой формы.

Общий модуль

Переиспользуемые функции для всей конфигурации. Требует настройки флагов Сервер/Клиент/Вызов сервера, иначе вызовы не скомпилируются.

Типичные ошибки и как их проверить

Самая частая ошибка — «Процедура или функция с указанным именем не определена». Причины: забыто слово Экспорт, функция находится в другом модуле, чем ожидает разработчик, либо у общего модуля не включён нужный флаг контекста (например, вызов с клиента, а модуль только серверный без «Вызова сервера»). Проверка начинается с места объявления функции и свойств модуля.

Вторая группа ошибок связана с параметрами: несовпадение количества аргументов, передача Неопределено там, где ожидается типизированное значение, неявное изменение параметра по ссылке. Отладчик конфигуратора позволяет поставить точку останова внутри функции и посмотреть фактические значения параметров на входе — это быстрее, чем гадать по тексту ошибки.

Третья группа — лишние серверные вызовы и потеря контекста. Симптом: форма открывается медленно, при работе «подвисает». Диагностируется замером производительности (Отладка → Замер производительности), где видно, сколько раз и сколько по времени вызывалась каждая функция.

Типичные ошибки
01
Забыт оператор Возврат в одной из веток условия — функция возвращает Неопределено, и логика выше молча ломается.
02
Изменение параметра по ссылке без слова Знач — переменная вызывающего кода меняется неожиданно для её владельца.
03
Серверный вызов внутри цикла по строкам таблицы — каждая итерация идёт на сервер, форма тормозит.
04
Привилегированный общий модуль с функцией, принимающей произвольный запрос — обход прав доступа пользователей.

Пошаговый разбор: написать и проверить функцию

Рассмотрим практический порядок действий на примере функции, проверяющей контрольное число ИНН или выполняющей любой другой прикладной расчёт. Схема одинакова для большинства задач.

Порядок действий
  1. 1
    Определите, где нужна функция: только внутри объекта — модуль объекта; везде — общий модуль с нужными флагами контекста.
  2. 2
    Объявите функцию: имя по смыслу, входные параметры со словом Знач, параметры по умолчанию в конце списка.
  3. 3
    Реализуйте тело так, чтобы каждая ветка логики завершалась оператором Возврат с осмысленным значением.
  4. 4
    Добавьте комментарий: что делает функция, какие параметры принимает, что возвращает и в каких случаях вернёт Неопределено.
  5. 5
    Проверьте синтаксис (Конфигурация → Проверка конфигурации) и прогоните функцию в отладчике на граничных значениях: пустая строка, ноль, Неопределено.
  6. 6
    Проверьте вызов из реального места: с клиента, с сервера, под пользователем с ограниченными правами.

Граничные значения при проверке особенно важны. Функция расчёта, отлично работающая на «круглых» тестовых данных, часто ломается на пустой табличной части, нулевом количестве или незаполненном реквизите. Проверка таких случаев до переноса в рабочую базу экономит значительно больше времени, чем поиск ошибки в эксплуатации.

Контрольные точки

Как проверить результат

Компиляция модуля
Норма

Проверка конфигурации проходит без ошибок, функция видна в местах вызова

Тревожный признак

Ошибка «функция не определена» — проверьте Экспорт и флаги общего модуля

Возвращаемое значение
Норма

В отладчике на каждой ветке функция возвращает ожидаемый тип

Тревожный признак

В какой-то ветке возвращается Неопределено вместо результата

Производительность
Норма

Один серверный вызов на пакет данных

Тревожный признак

Серверные вызовы в цикле, замер показывает сотни обращений

Функции — основа читаемого и поддерживаемого кода в 1С. Короткие функции с одним понятным действием, явными входными параметрами и предсказуемым результатом проще тестировать, переносить между конфигурациями и дорабатывать без риска сломать смежную логику.

Итог

Что важно запомнить

Функция обязана вернуть значение через Возврат на каждой ветке логики. Входные параметры помечайте Знач, слово Экспорт и флаги общего модуля определяют видимость, а серверные вызовы группируйте пакетами, чтобы не терять производительность.

Частые вопросы

Чем функция отличается от процедуры в 1С 8.3?

Функция обязана возвращать значение оператором Возврат и может использоваться внутри выражений: в условиях, присвоениях, как аргумент другой функции. Процедура только выполняет действия и ничего не возвращает, поэтому вызывается отдельным оператором. Если результат вычисления нужен вызывающему коду — нужна функция, если важно само действие (запись, сообщение) — процедура.

Почему возникает ошибка «Процедура или функция с указанным именем не определена»?

Чаще всего причины три: забыто ключевое слово Экспорт при объявлении, функция находится в другом модуле, чем предполагает вызов, либо у общего модуля не включён нужный контекст — например, вызов идёт с клиента, а модуль серверный без флага «Вызов сервера». Проверяйте место объявления и свойства модуля.

Можно ли вызвать функцию общего модуля с клиента?

Можно, если у общего модуля включены свойства «Сервер» и «Вызов сервера», а сама функция объявлена с Экспорт. Такой вызов — это обращение к серверу, поэтому частые вызовы в цикле стоит заменять одним пакетным вызовом с передачей массива данных.

Что вернёт функция, если не написать оператор Возврат?

Функция вернёт значение Неопределено. Это не вызовет ошибки компиляции, поэтому такой дефект проявляется только в логике: сравнения, арифметика и проверки заполнения выше по стеку начинают работать непредсказуемо. Каждая ветка условий в функции должна завершаться явным Возврат.

Когда использовать директиву &НаСервереБезКонтекста?

Когда функции нужны только переданные параметры и не требуются данные формы: расчёты, запросы к базе, поиск ссылок. Это самый дешёвый по ресурсам серверный вызов из формы, так как платформа не передаёт контекст формы на сервер и обратно.

Как передать из функции несколько результатов?

Удобнее всего вернуть структуру: внутри функции создаётся структура с именованными полями, заполняется результатами и возвращается через Возврат. Вызывающий код обращается к полям по имени. Альтернатива — изменение параметров по ссылке, но она хуже читается и чаще приводит к ошибкам.