Разработка и Конфигурация · 12 мин
Как сделать функцию в 1С: пошаговое руководство
Как написать функцию в 1С: объявление, параметры, возврат значения, экспорт, работа в модулях объектов и общих модулях, типичные ошибки и проверка результата.
Функция во встроенном языке 1С — это именованный блок кода, который принимает параметры, выполняет вычисления и обязательно возвращает результат через оператор Возврат. В отличие от процедуры, функцию можно вставить прямо в выражение: присвоить результат переменной, передать в другую функцию или использовать в условии. Это базовый инструмент структурирования кода: повторяющуюся логику выносят в функцию, чтобы не дублировать её в десятках мест конфигурации.
Функции создаются в конфигураторе внутри модулей: общих модулей, модулей объектов, модулей форм, модулей менеджеров. Выбор модуля определяет, откуда функция будет доступна — только внутри одного объекта или из любой точки прикладного решения. Ниже разобран синтаксис объявления, работа с параметрами, размещение в общих модулях, проверка результата и типичные ошибки, из-за которых функция не компилируется или возвращает не то, что ожидалось.
Где именно создавать функцию: выбор модуля
Прежде чем писать код, определите область видимости. Если логика нужна только одному объекту — например, расчёт итога в конкретном документе — функцию размещают в модуле этого объекта или в модуле формы. Если функция универсальна (форматирование строки, расчёт налога, проверка ИНН), её выносят в общий модуль, чтобы вызывать из любого места конфигурации по схеме ИмяОбщегоМодуля.ИмяФункции().
У общих модулей есть важные флаги. Флаг «Сервер» означает, что код выполняется на сервере, «Клиент (обычное приложение)» и «Клиент (управляемое приложение)» — на клиенте. Функция, работающая с базой данных (запросы, обращение к реквизитам объектов), должна выполняться на сервере. Если вызвать серверную логику с клиента без серверного общего модуля, получите ошибку компиляции или выполнения.
Куда поместить функцию
Синтаксис объявления функции
Минимальная функция состоит из ключевого слова Функция, имени, скобок с параметрами, тела и завершающего КонецФункции. Имя должно быть уникальным в пределах модуля, начинаться с буквы и не содержать пробелов — русские и английские идентификаторы допустимы и равноправны.
Функция РассчитатьСуммуСНДС(СуммаБезНДС, СтавкаНДС) Экспорт
СуммаНДС = СуммаБезНДС * СтавкаНДС / 100;
Возврат СуммаБезНДС + СуммаНДС;
КонецФункции
Слово Экспорт делает функцию видимой за пределами модуля. Без него функция считается локальной: её можно вызывать только из другого кода того же модуля. В общих модулях забытый Экспорт — самая частая причина ошибки «Процедура или функция с указанным именем не определена».
Тело функции выполняется сверху вниз до первого встреченного оператора Возврат. Код после Возврат в том же пути выполнения не выполняется. Если ни один Возврат не сработает, функция вернёт Неопределено, что часто приводит к трудноуловимым ошибкам в вызывающем коде.
Параметры: значения, умолчания и передача по ссылке
Параметры перечисляются в скобках через запятую. Если параметров нет, скобки всё равно обязательны: Функция ТекущаяВерсия() Экспорт. Для параметра можно задать значение по умолчанию — тогда вызывающий код вправе его не передавать:
Функция СформироватьЗаголовок(ИмяДокумента, Разделитель = " — ") Экспорт
Возврат ИмяДокумента + Разделитель + Формат(ТекущаяДатаСеанса(), "ДЛФ=D");
КонецФункции
Параметры со значениями по умолчанию должны стоять в конце списка — иначе компилятор выдаст ошибку. Если нужно явно пропустить средний параметр, в вызове ставят запятую без значения: СформироватьЗаголовок("Заказ", ).
По умолчанию параметры передаются по значению: внутри функции работает копия, и изменения не влияют на переменную вызывающего кода. Ключевое слово Знач перед параметром фиксирует это явно. Без Знач параметр передаётся по ссылке, и функция может изменить исходную переменную — это удобно для возврата нескольких результатов, но опасно неочевидными побочными эффектами.
Пошаговое создание функции в общем модуле
Типовой сценарий: нужна функция, которую будут вызывать несколько документов. Последовательность действий в конфигураторе одинакова для большинства версий платформы 8.3.
Флаг «Вызов сервера» часто упускают. Без него серверный общий модуль компилируется, но при попытке вызвать его функцию с клиента платформа выдаёт ошибку о нарушении прав доступа или о том, что модуль недоступен. Для модулей, которые вызываются только с сервера (например, из модулей объектов), этот флаг не нужен — и с точки зрения безопасности лишние флаги лучше не включать.
Функции в модулях формы: директивы компиляции
В управляемых формах код делится на клиентский и серверный с помощью директив &НаКлиенте, &НаСервере, &НаСервереБезКонтекста. Функция, объявленная с &НаКлиенте, не может напрямую выполнять запросы к базе — для этого её логику выносят в серверную функцию и вызывают её из клиентской.
&НаКлиенте
Процедура РассчитатьНажатие(Команда)
Итог = ПолучитьИтогНаСервере(Объект.Ссылка);
ПоказатьОповещениеПользователя("Итог: " + Итог);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьИтогНаСервере(Ссылка)
Возврат Ссылка.Товары.Итог("Сумма");
КонецФункции
Директива &НаСервереБезКонтекста предпочтительнее, когда функции не нужны реквизиты формы: она не тратит ресурсы на сериализацию данных формы при каждом вызове. Передавайте в такую функцию конкретные значения (ссылку, структуру параметров), а не всю форму.
Частый источник медленных форм — вызов серверной функции в цикле с клиента. Каждый вызов — отдельный обмен с сервером. Если нужно обработать таблицу из сотен строк, передайте данные на сервер одним вызовом и верните готовый результат.
Возврат значения и проверка результата
Функция может возвращать значение любого типа: число, строку, дату, булево, массив, структуру, ссылку на объект. Тип не объявляется заранее — язык слабо типизирован, поэтому ответственность за корректность типа лежит на разработчике. Хорошая практика — отражать тип результата в имени: НайтиКонтрагентаПоИНН() подразумевает ссылку или Неопределено, ЭтоВалидныйИНН() — булево.
После внедрения функции проверьте её на граничных случаях: пустые параметры, нулевые значения, отсутствие данных в базе. Если функция ищет объект по критерию и ничего не нашла, явно возвращайте Неопределено и обрабатывайте этот случай в вызывающем коде — иначе получите ошибку «Поле объекта не обнаружено» при обращении к реквизиту несуществующей ссылки.
Как проверить результат
Конфигуратор сохраняет модуль без сообщений об ошибках в окне служебных сообщений
Ошибки вида «Переменная не определена» или «Ожидается символ ';'»
В отладчике на строке Возврат видно ожидаемое значение нужного типа
Возвращается Неопределено, хотя данные есть — значит, Возврат стоит не во всех ветках условий
Функция доступна через ИмяМодуля.ИмяФункции() и выполняется
Ошибка «Процедура или функция не определена» — нет слова Экспорт или не включён «Вызов сервера»
Функция возвращает предсказуемое значение (Неопределено, 0, пустую строку)
Исключение или аварийное завершение сеанса
Типичные ошибки и ограничения
Большинство проблем с функциями у начинающих разработчиков сводится к нескольким повторяющимся сценариям: забытый Экспорт, Возврат не во всех ветках условий, обращение к базе данных из клиентского контекста и изменение параметров по ссылке без осознания последствий.
Ещё одно ограничение: функции общих модулей, помеченных как «Привилегированный», выполняются без проверки прав доступа. Это удобно для служебных операций, но опасно — через такую функцию пользователь с ограниченными правами может косвенно получить данные, к которым доступа не имеет. Включайте привилегированный режим осознанно и не выносите туда функции, возвращающие произвольные данные по параметрам вызова.
Отладка функции
Отладчик конфигуратора запускается через меню «Отладка» → «Начать отладку» (F5). Поставьте точку останова (F9) на первой строке тела функции и выполните действие, которое её вызывает. В окне «Выражения» (Ctrl+Alt+W) добавьте имена параметров и локальных переменных — так видно, что реально пришло на вход и как меняются значения по шагам (F8 — шаг через, F10 — шаг вокруг).
Если точка останова не срабатывает, проверьте три вещи: включён ли режим отладки в свойствах информационной базы, тот ли это сеанс (серверный код отлаживается через подключение к серверному процессу), и действительно ли вызывается именно ваша функция — возможно, условие в вызывающем коде не выполняется. Для серверных вызовов из веб-клиента отладка настраивается отдельно через параметр запуска сервера.
Что важно запомнить
Функция объявляется через «Функция Имя(Параметры) Экспорт» и обязана вернуть значение оператором Возврат на любом пути выполнения. Универсальные функции размещайте в общих модулях с нужными флагами, локальные — в модулях объектов и форм. Проверяйте граничные случаи и не правьте типовой код напрямую.
Частые вопросы
Чем функция отличается от процедуры в 1С?
Функция обязана вернуть значение через оператор Возврат, и её вызов можно использовать внутри выражения: присваивания, условия, арифметической операции. Процедура ничего не возвращает и вызывается отдельным оператором. Если результат не нужен, а нужно только действие (записать объект, вывести сообщение) — используйте процедуру.
Почему функция возвращает Неопределено, хотя данные есть?
Почти всегда причина в том, что оператор Возврат стоит не на всех путях выполнения: например, только внутри Если, а условие не сработало. Поставьте в конце тела функции Возврат со значением по умолчанию и проверьте в отладчике, какая ветка условий реально выполняется.
Можно ли вызвать функцию одного общего модуля из другого?
Да, если функция объявлена со словом Экспорт и контексты выполнения совместимы: серверный модуль может вызывать другой серверный модуль, клиентский — клиентский. Вызов серверного модуля из клиентского возможен только при включённом флаге «Вызов сервера».
Как передать в функцию таблицу значений или массив?
Просто укажите переменную как параметр — коллекции передаются по ссылке, и функция получит доступ к их содержимому. Учтите, что изменения коллекции внутри функции будут видны и в вызывающем коде; если это нежелательно, создайте копию методом Скопировать() перед передачей.
Что делать, если нельзя менять типовую конфигурацию?
Используйте расширение конфигурации: оно позволяет добавлять собственные общие модули и функции, а также дополнять типовые методы аннотациями &Перед, &После, &Вместо. Расширение не нарушает поддержку и обновляется независимо от основной конфигурации.
Как узнать, откуда вызывается моя функция?
В отладчике используйте окно «Стек вызовов» (Ctrl+Alt+C): оно показывает цепочку модулей и строк, из которых пришло выполнение. Также можно поставить точку останова с условием или вывести трассировку через Сообщить() на время поиска проблемы.