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

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

Как сделать функцию в 1С: пошаговое руководство

Как написать функцию в 1С: объявление, параметры, возврат значения, экспорт, работа в модулях объектов и общих модулях, типичные ошибки и проверка результата.

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

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

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

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

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

Маршрут решения

Куда поместить функцию

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

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

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

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

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

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

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

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

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

Параметры: значения, умолчания и передача по ссылке

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

Функция СформироватьЗаголовок(ИмяДокумента, Разделитель = " — ") Экспорт

Возврат ИмяДокумента + Разделитель + Формат(ТекущаяДатаСеанса(), "ДЛФ=D");

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

Параметры со значениями по умолчанию должны стоять в конце списка — иначе компилятор выдаст ошибку. Если нужно явно пропустить средний параметр, в вызове ставят запятую без значения: СформироватьЗаголовок("Заказ", ).

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

Пошаговое создание функции в общем модуле

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

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

Функции в модулях формы: директивы компиляции

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

&НаКлиенте

Процедура РассчитатьНажатие(Команда)

Итог = ПолучитьИтогНаСервере(Объект.Ссылка);

ПоказатьОповещениеПользователя("Итог: " + Итог);

КонецПроцедуры

&НаСервереБезКонтекста

Функция ПолучитьИтогНаСервере(Ссылка)

Возврат Ссылка.Товары.Итог("Сумма");

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

Директива &НаСервереБезКонтекста предпочтительнее, когда функции не нужны реквизиты формы: она не тратит ресурсы на сериализацию данных формы при каждом вызове. Передавайте в такую функцию конкретные значения (ссылку, структуру параметров), а не всю форму.

Частый источник медленных форм — вызов серверной функции в цикле с клиента. Каждый вызов — отдельный обмен с сервером. Если нужно обработать таблицу из сотен строк, передайте данные на сервер одним вызовом и верните готовый результат.
ПЗ
Практическое замечание

Возврат значения и проверка результата

Функция может возвращать значение любого типа: число, строку, дату, булево, массив, структуру, ссылку на объект. Тип не объявляется заранее — язык слабо типизирован, поэтому ответственность за корректность типа лежит на разработчике. Хорошая практика — отражать тип результата в имени: НайтиКонтрагентаПоИНН() подразумевает ссылку или Неопределено, ЭтоВалидныйИНН() — булево.

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

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

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

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

Конфигуратор сохраняет модуль без сообщений об ошибках в окне служебных сообщений

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

Ошибки вида «Переменная не определена» или «Ожидается символ ';'»

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

В отладчике на строке Возврат видно ожидаемое значение нужного типа

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

Возвращается Неопределено, хотя данные есть — значит, Возврат стоит не во всех ветках условий

Вызов из другого модуля
Норма

Функция доступна через ИмяМодуля.ИмяФункции() и выполняется

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

Ошибка «Процедура или функция не определена» — нет слова Экспорт или не включён «Вызов сервера»

Поведение при пустых данных
Норма

Функция возвращает предсказуемое значение (Неопределено, 0, пустую строку)

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

Исключение или аварийное завершение сеанса

Типичные ошибки и ограничения

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

Типичные ошибки
01
Нет слова Экспорт в общем модуле — вызов извне падает с ошибкой «функция не определена».
02
Возврат стоит только внутри Если — при невыполнении условия функция молча вернёт Неопределено.
03
Серверный общий модуль без флага «Вызов сервера» вызывают с клиента — ошибка доступа в тонком клиенте.
04
Попытка выполнить запрос к базе в функции с директивой &НаКлиенте — ошибка компиляции о недопустимости операции.
05
Изменение параметра-структуры внутри функции без Знач — вызывающий код получает неожиданно изменённые данные.
06
Имя функции совпадает с именем метода платформы или другой функции модуля — неоднозначность и ошибки компиляции.

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

Отладка функции

Отладчик конфигуратора запускается через меню «Отладка» → «Начать отладку» (F5). Поставьте точку останова (F9) на первой строке тела функции и выполните действие, которое её вызывает. В окне «Выражения» (Ctrl+Alt+W) добавьте имена параметров и локальных переменных — так видно, что реально пришло на вход и как меняются значения по шагам (F8 — шаг через, F10 — шаг вокруг).

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

Итог

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

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

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

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

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

Почему функция возвращает Неопределено, хотя данные есть?

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

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

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

Как передать в функцию таблицу значений или массив?

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

Что делать, если нельзя менять типовую конфигурацию?

Используйте расширение конфигурации: оно позволяет добавлять собственные общие модули и функции, а также дополнять типовые методы аннотациями &Перед, &После, &Вместо. Расширение не нарушает поддержку и обновляется независимо от основной конфигурации.

Как узнать, откуда вызывается моя функция?

В отладчике используйте окно «Стек вызовов» (Ctrl+Alt+C): оно показывает цепочку модулей и строк, из которых пришло выполнение. Также можно поставить точку останова с условием или вывести трассировку через Сообщить() на время поиска проблемы.